Repository: slicol/SGF Branch: master Commit: c24cf335cae7 Files: 625 Total size: 3.8 MB Directory structure: gitextract_tlw7vj5v/ ├── .gitignore ├── Apps/ │ ├── DirConfig.json │ ├── ILRuntime.dll.config │ ├── SGFAppDemo.exe.config │ ├── SGFAppILRScript.dll.config │ ├── SGFCore.dll.config │ ├── SGFCore.xml │ ├── SGFServer.exe.config │ └── SGFServerDemo.exe.config ├── ILRuntime/ │ ├── App.config │ ├── ILRuntime/ │ │ ├── Adapters/ │ │ │ └── Editor/ │ │ │ └── ILRuntimeCLRBinding.cs │ │ ├── CLR/ │ │ │ ├── Method/ │ │ │ │ ├── CLRMethod.cs │ │ │ │ ├── ExceptionHandler.cs │ │ │ │ ├── ILMethod.cs │ │ │ │ └── IMethod.cs │ │ │ ├── TypeSystem/ │ │ │ │ ├── CLRType.cs │ │ │ │ ├── ILGenericParameterType.cs │ │ │ │ ├── ILType.cs │ │ │ │ └── IType.cs │ │ │ └── Utils/ │ │ │ └── Extensions.cs │ │ ├── Other/ │ │ │ ├── ByReferenceKeyComparer.cs │ │ │ ├── DelegateExportAttribute.cs │ │ │ ├── NeedAdaptorAttribute.cs │ │ │ ├── ThreadSafeDictionary.cs │ │ │ └── UncheckedList.cs │ │ ├── Reflection/ │ │ │ ├── Extensions.cs │ │ │ ├── ILRuntimeConstructorInfo.cs │ │ │ ├── ILRuntimeFieldInfo.cs │ │ │ ├── ILRuntimeMethodInfo.cs │ │ │ ├── ILRuntimeParameterInfo.cs │ │ │ ├── ILRuntimePropertyInfo.cs │ │ │ ├── ILRuntimeType.cs │ │ │ └── ILRuntimeWrapperType.cs │ │ └── Runtime/ │ │ ├── Adaptors/ │ │ │ └── CLRCrossBindingAdaptors.cs │ │ ├── CLRBinding/ │ │ │ ├── BindingCodeGenerator.cs │ │ │ ├── BindingGeneratorExtensions.cs │ │ │ ├── CommonBindingGenerator.cs │ │ │ ├── ConstructorBindingGenerator.cs │ │ │ ├── FieldBindingGenerator.cs │ │ │ ├── MethodBindingGenerator.cs │ │ │ └── ValueTypeBindingGenerator.cs │ │ ├── Debugger/ │ │ │ ├── BreakPointContext.cs │ │ │ ├── BreakpointInfo.cs │ │ │ ├── DebugMessageType.cs │ │ │ ├── DebugService.cs │ │ │ ├── DebugSocket.cs │ │ │ ├── DebuggerServer/ │ │ │ │ └── DebuggerServer.cs │ │ │ ├── Protocol/ │ │ │ │ ├── CSBindBreakpoint.cs │ │ │ │ ├── CSDeleteBreakpoint.cs │ │ │ │ ├── CSExecute.cs │ │ │ │ ├── CSResolveVariable.cs │ │ │ │ ├── CSStep.cs │ │ │ │ ├── SCAttachResult.cs │ │ │ │ ├── SCBindBreakpointResult.cs │ │ │ │ ├── SCBreakpointHit.cs │ │ │ │ ├── SCModuleLoaded.cs │ │ │ │ ├── SCResolveVariableResult.cs │ │ │ │ ├── SCStepComplete.cs │ │ │ │ └── SCThreadStarted.cs │ │ │ ├── StackFrameInfo.cs │ │ │ ├── StepTypes.cs │ │ │ └── VariableInfo.cs │ │ ├── Enviorment/ │ │ │ ├── AppDomain.cs │ │ │ ├── CLRRedirections.cs │ │ │ ├── CrossBindingAdaptor.cs │ │ │ ├── DelegateManager.cs │ │ │ ├── ILContext.cs │ │ │ └── ValueTypeBinder.cs │ │ ├── Extensions.cs │ │ ├── Intepreter/ │ │ │ ├── DelegateAdapter.cs │ │ │ ├── ILIntepreter.cs │ │ │ ├── ILRuntimeException.cs │ │ │ ├── ILTypeInstance.cs │ │ │ └── OpCodes/ │ │ │ ├── OpCode.cs │ │ │ └── OpCodeEnum.cs │ │ └── Stack/ │ │ ├── RuntimeStack.cs │ │ ├── StackFrame.cs │ │ └── StackObject.cs │ ├── ILRuntime.csproj │ ├── ILRuntime.csproj.user │ ├── Mono.Cecil.20/ │ │ └── MonoCecil/ │ │ ├── Mono/ │ │ │ ├── Actions.cs │ │ │ ├── Empty.cs │ │ │ └── Funcs.cs │ │ ├── Mono.Cecil/ │ │ │ ├── ArrayType.cs │ │ │ ├── AssemblyDefinition.cs │ │ │ ├── AssemblyFlags.cs │ │ │ ├── AssemblyHashAlgorithm.cs │ │ │ ├── AssemblyLinkedResource.cs │ │ │ ├── AssemblyNameDefinition.cs │ │ │ ├── AssemblyNameReference.cs │ │ │ ├── AssemblyReader.cs │ │ │ ├── AssemblyWriter.cs │ │ │ ├── BaseAssemblyResolver.cs │ │ │ ├── CallSite.cs │ │ │ ├── CustomAttribute.cs │ │ │ ├── DefaultAssemblyResolver.cs │ │ │ ├── EmbeddedResource.cs │ │ │ ├── EventAttributes.cs │ │ │ ├── EventDefinition.cs │ │ │ ├── EventReference.cs │ │ │ ├── ExportedType.cs │ │ │ ├── FieldAttributes.cs │ │ │ ├── FieldDefinition.cs │ │ │ ├── FieldReference.cs │ │ │ ├── FileAttributes.cs │ │ │ ├── FunctionPointerType.cs │ │ │ ├── GenericInstanceMethod.cs │ │ │ ├── GenericInstanceType.cs │ │ │ ├── GenericParameter.cs │ │ │ ├── GenericParameterAttributes.cs │ │ │ ├── IConstantProvider.cs │ │ │ ├── ICustomAttributeProvider.cs │ │ │ ├── IGenericInstance.cs │ │ │ ├── IGenericParameterProvider.cs │ │ │ ├── IMarshalInfoProvider.cs │ │ │ ├── IMemberDefinition.cs │ │ │ ├── IMetadataScope.cs │ │ │ ├── IMetadataTokenProvider.cs │ │ │ ├── IMethodSignature.cs │ │ │ ├── Import.cs │ │ │ ├── LinkedResource.cs │ │ │ ├── ManifestResourceAttributes.cs │ │ │ ├── MarshalInfo.cs │ │ │ ├── MemberDefinitionCollection.cs │ │ │ ├── MemberReference.cs │ │ │ ├── MetadataResolver.cs │ │ │ ├── MetadataSystem.cs │ │ │ ├── MethodAttributes.cs │ │ │ ├── MethodCallingConvention.cs │ │ │ ├── MethodDefinition.cs │ │ │ ├── MethodImplAttributes.cs │ │ │ ├── MethodReference.cs │ │ │ ├── MethodReturnType.cs │ │ │ ├── MethodSemanticsAttributes.cs │ │ │ ├── MethodSpecification.cs │ │ │ ├── Modifiers.cs │ │ │ ├── ModuleDefinition.cs │ │ │ ├── ModuleKind.cs │ │ │ ├── ModuleReference.cs │ │ │ ├── NativeType.cs │ │ │ ├── PInvokeAttributes.cs │ │ │ ├── PInvokeInfo.cs │ │ │ ├── ParameterAttributes.cs │ │ │ ├── ParameterDefinition.cs │ │ │ ├── ParameterDefinitionCollection.cs │ │ │ ├── ParameterReference.cs │ │ │ ├── PinnedType.cs │ │ │ ├── PointerType.cs │ │ │ ├── PropertyAttributes.cs │ │ │ ├── PropertyDefinition.cs │ │ │ ├── PropertyReference.cs │ │ │ ├── ReferenceType.cs │ │ │ ├── Resource.cs │ │ │ ├── SecurityDeclaration.cs │ │ │ ├── SentinelType.cs │ │ │ ├── TargetRuntime.cs │ │ │ ├── TypeAttributes.cs │ │ │ ├── TypeDefinition.cs │ │ │ ├── TypeDefinitionCollection.cs │ │ │ ├── TypeParser.cs │ │ │ ├── TypeReference.cs │ │ │ ├── TypeSpecification.cs │ │ │ ├── TypeSystem.cs │ │ │ └── VariantType.cs │ │ ├── Mono.Cecil.Cil/ │ │ │ ├── Code.cs │ │ │ ├── CodeReader.cs │ │ │ ├── CodeWriter.cs │ │ │ ├── Document.cs │ │ │ ├── ExceptionHandler.cs │ │ │ ├── ILProcessor.cs │ │ │ ├── Instruction.cs │ │ │ ├── MethodBody.cs │ │ │ ├── OpCode.cs │ │ │ ├── OpCodes.cs │ │ │ ├── SequencePoint.cs │ │ │ ├── Symbols.cs │ │ │ ├── VariableDefinition.cs │ │ │ └── VariableReference.cs │ │ ├── Mono.Cecil.Metadata/ │ │ │ ├── BlobHeap.cs │ │ │ ├── Buffers.cs │ │ │ ├── CodedIndex.cs │ │ │ ├── ElementType.cs │ │ │ ├── GuidHeap.cs │ │ │ ├── Heap.cs │ │ │ ├── MetadataToken.cs │ │ │ ├── Row.cs │ │ │ ├── StringHeap.cs │ │ │ ├── TableHeap.cs │ │ │ ├── TokenType.cs │ │ │ ├── UserStringHeap.cs │ │ │ └── Utilities.cs │ │ ├── Mono.Cecil.PE/ │ │ │ ├── BinaryStreamReader.cs │ │ │ ├── BinaryStreamWriter.cs │ │ │ ├── ByteBuffer.cs │ │ │ ├── ByteBufferEqualityComparer.cs │ │ │ ├── DataDirectory.cs │ │ │ ├── Image.cs │ │ │ ├── ImageReader.cs │ │ │ ├── ImageWriter.cs │ │ │ ├── Section.cs │ │ │ └── TextMap.cs │ │ ├── Mono.Collections.Generic/ │ │ │ ├── Collection.cs │ │ │ └── ReadOnlyCollection.cs │ │ └── Mono.Security.Cryptography/ │ │ ├── CryptoConvert.cs │ │ └── CryptoService.cs │ └── Properties/ │ └── AssemblyInfo.cs ├── Libs/ │ ├── PublishLibrary.bat │ ├── SGFAppDemo.exe.config │ ├── SGFAppILRScript.dll.config │ └── SGFCore.dll.config ├── README.md ├── SGF.sln ├── SGFAppCommon/ │ ├── Data/ │ │ ├── PlayerData.cs │ │ ├── RoomData.cs │ │ └── UserData.cs │ ├── Properties/ │ │ └── AssemblyInfo.cs │ ├── Proto/ │ │ ├── HeartBeatProto.cs │ │ ├── LoginProto.cs │ │ └── ProtoCmd.cs │ └── SGFAppCommon.csproj ├── SGFAppDemo/ │ ├── App.config │ ├── AppMain.cs │ ├── Framework/ │ │ ├── SGFGameDefine.cs │ │ ├── SGFGameMainLoop.cs │ │ └── SGFGameObject.cs │ ├── GlobalEvent.cs │ ├── ModuleDef.cs │ ├── Modules/ │ │ └── Version/ │ │ └── VersionModule.cs │ ├── Program.cs │ ├── Properties/ │ │ └── AssemblyInfo.cs │ ├── SGFAppDemo.csproj │ ├── SGFGameDefine.cs │ ├── SGFGameMainLoop.cs │ ├── SGFGameObject.cs │ └── Services/ │ └── Online/ │ ├── HeartBeatHandler.cs │ ├── OnlineManager.cs │ ├── ServerProfiler.cs │ └── ServerTestBot.cs ├── SGFAppILRScript/ │ ├── App.config │ ├── ModuleDef.cs │ ├── Modules/ │ │ ├── Login/ │ │ │ └── LoginModule.cs │ │ └── Room/ │ │ └── RoomModule.cs │ ├── Properties/ │ │ └── AssemblyInfo.cs │ ├── SGFAppILRScript.csproj │ ├── SGFAppILRScript.csproj.user │ └── ScriptMain.cs ├── SGFCore/ │ ├── App.config │ ├── Class1.cs │ ├── Codec/ │ │ ├── MiniJSON.cs │ │ ├── PBSerializer.cs │ │ └── SGFEncoding.cs │ ├── Event/ │ │ └── Signal.cs │ ├── Extension/ │ │ ├── CollectionExtensions.cs │ │ ├── ObjectExtensions.cs │ │ ├── StreamExtension.cs │ │ └── StringExtensions.cs │ ├── G3Lite/ │ │ ├── IndexTypes.cs │ │ ├── MathUtil.cs │ │ ├── Matrix3.cs │ │ ├── Quaternion.cs │ │ ├── Vector2.cs │ │ ├── Vector3.cs │ │ └── Vector4.cs │ ├── IPCWork/ │ │ ├── IPCConfig.cs │ │ ├── IPCManager.cs │ │ └── IPCMessage.cs │ ├── Marshals/ │ │ ├── MarshalArray.cs │ │ └── MarshalList.cs │ ├── MathLite/ │ │ └── SGFRandom.cs │ ├── Module/ │ │ ├── GeneralModule.cs │ │ ├── IModuleActivator.cs │ │ ├── ModuleBase.cs │ │ ├── ModuleManager.cs │ │ └── NativeModuleActivator.cs │ ├── MvvmLite/ │ │ ├── MvvmBinding.cs │ │ ├── MvvmCommand.cs │ │ ├── MvvmManager.cs │ │ ├── MvvmModel.cs │ │ └── MvvmViewModel.cs │ ├── Network/ │ │ ├── Core/ │ │ │ ├── KCP/ │ │ │ │ ├── KCPSocket.cs │ │ │ │ ├── LICENSE.txt │ │ │ │ ├── kcp.cs │ │ │ │ └── switch_queue.cs │ │ │ ├── NetBuffer.cs │ │ │ ├── NetErrorCode.cs │ │ │ ├── RPCLite/ │ │ │ │ ├── RPCManagerBase.cs │ │ │ │ └── RPCMessage.cs │ │ │ ├── SocketAsyncEventArgsPool.cs │ │ │ └── UdpSocket.cs │ │ ├── Debuger/ │ │ │ ├── NetDebugFile.cs │ │ │ ├── NetDebuger.cs │ │ │ └── net_debuger.cs │ │ ├── FSPLite/ │ │ │ ├── Client/ │ │ │ │ ├── FSPClient.cs │ │ │ │ ├── FSPFrameController.cs │ │ │ │ └── FSPManager.cs │ │ │ ├── FSPBasicCmd.cs │ │ │ ├── FSPGameEndReason.cs │ │ │ ├── FSPGameState.cs │ │ │ ├── FSPLiteData.cs │ │ │ └── Server/ │ │ │ ├── FSPGame.cs │ │ │ ├── FSPGateway.cs │ │ │ ├── FSPManager.cs │ │ │ ├── FSPPlayer.cs │ │ │ └── FSPSession.cs │ │ ├── General/ │ │ │ ├── Client/ │ │ │ │ ├── IConnection.cs │ │ │ │ ├── KCPConnection.cs │ │ │ │ ├── NetManager.cs │ │ │ │ ├── RPCManager.cs │ │ │ │ ├── TcpConnection.cs │ │ │ │ └── UdpConnection.cs │ │ │ ├── ConnectionType.cs │ │ │ ├── NetDefine.cs │ │ │ ├── NetPacket.cs │ │ │ ├── Proto/ │ │ │ │ ├── NetErrorProto.cs │ │ │ │ ├── NetMessage.cs │ │ │ │ ├── ProfilerTestProto.cs │ │ │ │ └── ProtocolHead.cs │ │ │ ├── Server/ │ │ │ │ ├── IGateway.cs │ │ │ │ ├── ISession.cs │ │ │ │ ├── KCPGateway.cs │ │ │ │ ├── KCPSession.cs │ │ │ │ ├── NetManager.cs │ │ │ │ ├── RPCManager.cs │ │ │ │ ├── TcpGateway.cs │ │ │ │ ├── TcpSession.cs │ │ │ │ ├── UdpGateway.cs │ │ │ │ └── UdpSession.cs │ │ │ └── TcpConnectionBase.cs │ │ └── Utils/ │ │ ├── DnsUtils.cs │ │ ├── IPUtils.cs │ │ └── NetUtils.cs │ ├── Properties/ │ │ └── AssemblyInfo.cs │ ├── SGFCore.csproj │ ├── SGFCore.csproj.user │ ├── Server/ │ │ ├── MainLoop.cs │ │ ├── ServerConfig.cs │ │ ├── ServerManager.cs │ │ └── ServerModule.cs │ ├── Threading/ │ │ └── ThreadPool.cs │ ├── Timers/ │ │ └── Timer.cs │ └── Utils/ │ ├── AppPrefs.cs │ ├── CmdlineUtils.cs │ ├── ConsoleInput.cs │ ├── DictionarySafe.cs │ ├── FPSUtils.cs │ ├── FileUtils.cs │ ├── MapList.cs │ ├── ObjectDumpUtils.cs │ ├── PathUtils.cs │ ├── SGFTime.cs │ ├── Singleton.cs │ ├── StringUtils.cs │ ├── ThrowHelper.cs │ ├── TimeUtils.cs │ └── URLUtils.cs ├── SGFCoreTest/ │ ├── Properties/ │ │ └── AssemblyInfo.cs │ ├── SGFCoreTest.csproj │ ├── TestMarshalArray.cs │ └── TestMarshalList.cs ├── SGFDebuger/ │ ├── Debuger.cs │ ├── Properties/ │ │ └── AssemblyInfo.cs │ └── SGFDebuger.csproj ├── SGFServerLite/ │ ├── App.config │ ├── GameServer/ │ │ └── GameServer.cs │ ├── Program.cs │ ├── Properties/ │ │ └── AssemblyInfo.cs │ ├── SGFServerDemo.csproj │ └── ZoneServer/ │ ├── Online/ │ │ └── OnlineManager.cs │ ├── Room/ │ │ ├── Room.cs │ │ └── RoomManager.cs │ ├── ServerContext.cs │ └── ZoneServer.cs ├── SGFUnity/ │ ├── Class1.cs │ ├── Common/ │ │ ├── AppPrefs.cs │ │ ├── DelayInvoker.cs │ │ ├── MonoHelper.cs │ │ └── MonoSingleton.cs │ ├── DebugerGUI/ │ │ ├── NetDebugerGUI.cs │ │ ├── SGFDebugerGUI.cs │ │ └── SGFDebugerGUIBase.cs │ ├── Extension/ │ │ ├── BitmapDrawingExtensions.cs │ │ ├── TransformExtensions.cs │ │ └── VectorExtensions.cs │ ├── ILR/ │ │ ├── DebugerILR/ │ │ │ ├── DebugerMethodRedirector.cs │ │ │ └── ILogTagAdaptor.cs │ │ ├── DelegateConvertor.cs │ │ ├── ILRManager.cs │ │ ├── ModuleILR/ │ │ │ ├── GeneralModuleAdaptor.cs │ │ │ └── ILRModuleActivator.cs │ │ └── UIILR/ │ │ ├── ILRUILoading.cs │ │ ├── ILRUILoadingAdaptor.cs │ │ ├── ILRUIPage.cs │ │ ├── ILRUIPageAdaptor.cs │ │ ├── ILRUIPanel.cs │ │ ├── ILRUIPanelAdaptor.cs │ │ ├── ILRUIWidget.cs │ │ ├── ILRUIWidgetAdaptor.cs │ │ ├── ILRUIWindow.cs │ │ └── ILRUIWindowAdaptor.cs │ ├── ILRuntime/ │ │ ├── Adapters/ │ │ │ └── Editor/ │ │ │ └── ILRuntimeCLRBinding.cs │ │ ├── CLR/ │ │ │ ├── Method/ │ │ │ │ ├── CLRMethod.cs │ │ │ │ ├── ExceptionHandler.cs │ │ │ │ ├── ILMethod.cs │ │ │ │ └── IMethod.cs │ │ │ ├── TypeSystem/ │ │ │ │ ├── CLRType.cs │ │ │ │ ├── ILGenericParameterType.cs │ │ │ │ ├── ILType.cs │ │ │ │ └── IType.cs │ │ │ └── Utils/ │ │ │ └── Extensions.cs │ │ ├── Other/ │ │ │ ├── ByReferenceKeyComparer.cs │ │ │ ├── DelegateExportAttribute.cs │ │ │ ├── NeedAdaptorAttribute.cs │ │ │ ├── ThreadSafeDictionary.cs │ │ │ └── UncheckedList.cs │ │ ├── Reflection/ │ │ │ ├── Extensions.cs │ │ │ ├── ILRuntimeConstructorInfo.cs │ │ │ ├── ILRuntimeFieldInfo.cs │ │ │ ├── ILRuntimeMethodInfo.cs │ │ │ ├── ILRuntimeParameterInfo.cs │ │ │ ├── ILRuntimePropertyInfo.cs │ │ │ ├── ILRuntimeType.cs │ │ │ └── ILRuntimeWrapperType.cs │ │ └── Runtime/ │ │ ├── Adaptors/ │ │ │ └── CLRCrossBindingAdaptors.cs │ │ ├── CLRBinding/ │ │ │ ├── BindingCodeGenerator.cs │ │ │ ├── BindingGeneratorExtensions.cs │ │ │ ├── CommonBindingGenerator.cs │ │ │ ├── ConstructorBindingGenerator.cs │ │ │ ├── FieldBindingGenerator.cs │ │ │ ├── MethodBindingGenerator.cs │ │ │ └── ValueTypeBindingGenerator.cs │ │ ├── Debugger/ │ │ │ ├── BreakPointContext.cs │ │ │ ├── BreakpointInfo.cs │ │ │ ├── DebugMessageType.cs │ │ │ ├── DebugService.cs │ │ │ ├── DebugSocket.cs │ │ │ ├── DebuggerServer/ │ │ │ │ └── DebuggerServer.cs │ │ │ ├── Protocol/ │ │ │ │ ├── CSBindBreakpoint.cs │ │ │ │ ├── CSDeleteBreakpoint.cs │ │ │ │ ├── CSExecute.cs │ │ │ │ ├── CSResolveVariable.cs │ │ │ │ ├── CSStep.cs │ │ │ │ ├── SCAttachResult.cs │ │ │ │ ├── SCBindBreakpointResult.cs │ │ │ │ ├── SCBreakpointHit.cs │ │ │ │ ├── SCModuleLoaded.cs │ │ │ │ ├── SCResolveVariableResult.cs │ │ │ │ ├── SCStepComplete.cs │ │ │ │ └── SCThreadStarted.cs │ │ │ ├── StackFrameInfo.cs │ │ │ ├── StepTypes.cs │ │ │ └── VariableInfo.cs │ │ ├── Enviorment/ │ │ │ ├── AppDomain.cs │ │ │ ├── CLRRedirections.cs │ │ │ ├── CrossBindingAdaptor.cs │ │ │ ├── DelegateManager.cs │ │ │ ├── ILContext.cs │ │ │ └── ValueTypeBinder.cs │ │ ├── Extensions.cs │ │ ├── Intepreter/ │ │ │ ├── DelegateAdapter.cs │ │ │ ├── ILIntepreter.cs │ │ │ ├── ILRuntimeException.cs │ │ │ ├── ILTypeInstance.cs │ │ │ └── OpCodes/ │ │ │ ├── OpCode.cs │ │ │ └── OpCodeEnum.cs │ │ └── Stack/ │ │ ├── RuntimeStack.cs │ │ ├── StackFrame.cs │ │ └── StackObject.cs │ ├── Mono.Cecil.20/ │ │ └── MonoCecil/ │ │ ├── Mono/ │ │ │ ├── Actions.cs │ │ │ ├── Empty.cs │ │ │ └── Funcs.cs │ │ ├── Mono.Cecil/ │ │ │ ├── ArrayType.cs │ │ │ ├── AssemblyDefinition.cs │ │ │ ├── AssemblyFlags.cs │ │ │ ├── AssemblyHashAlgorithm.cs │ │ │ ├── AssemblyLinkedResource.cs │ │ │ ├── AssemblyNameDefinition.cs │ │ │ ├── AssemblyNameReference.cs │ │ │ ├── AssemblyReader.cs │ │ │ ├── AssemblyWriter.cs │ │ │ ├── BaseAssemblyResolver.cs │ │ │ ├── CallSite.cs │ │ │ ├── CustomAttribute.cs │ │ │ ├── DefaultAssemblyResolver.cs │ │ │ ├── EmbeddedResource.cs │ │ │ ├── EventAttributes.cs │ │ │ ├── EventDefinition.cs │ │ │ ├── EventReference.cs │ │ │ ├── ExportedType.cs │ │ │ ├── FieldAttributes.cs │ │ │ ├── FieldDefinition.cs │ │ │ ├── FieldReference.cs │ │ │ ├── FileAttributes.cs │ │ │ ├── FunctionPointerType.cs │ │ │ ├── GenericInstanceMethod.cs │ │ │ ├── GenericInstanceType.cs │ │ │ ├── GenericParameter.cs │ │ │ ├── GenericParameterAttributes.cs │ │ │ ├── IConstantProvider.cs │ │ │ ├── ICustomAttributeProvider.cs │ │ │ ├── IGenericInstance.cs │ │ │ ├── IGenericParameterProvider.cs │ │ │ ├── IMarshalInfoProvider.cs │ │ │ ├── IMemberDefinition.cs │ │ │ ├── IMetadataScope.cs │ │ │ ├── IMetadataTokenProvider.cs │ │ │ ├── IMethodSignature.cs │ │ │ ├── Import.cs │ │ │ ├── LinkedResource.cs │ │ │ ├── ManifestResourceAttributes.cs │ │ │ ├── MarshalInfo.cs │ │ │ ├── MemberDefinitionCollection.cs │ │ │ ├── MemberReference.cs │ │ │ ├── MetadataResolver.cs │ │ │ ├── MetadataSystem.cs │ │ │ ├── MethodAttributes.cs │ │ │ ├── MethodCallingConvention.cs │ │ │ ├── MethodDefinition.cs │ │ │ ├── MethodImplAttributes.cs │ │ │ ├── MethodReference.cs │ │ │ ├── MethodReturnType.cs │ │ │ ├── MethodSemanticsAttributes.cs │ │ │ ├── MethodSpecification.cs │ │ │ ├── Modifiers.cs │ │ │ ├── ModuleDefinition.cs │ │ │ ├── ModuleKind.cs │ │ │ ├── ModuleReference.cs │ │ │ ├── NativeType.cs │ │ │ ├── PInvokeAttributes.cs │ │ │ ├── PInvokeInfo.cs │ │ │ ├── ParameterAttributes.cs │ │ │ ├── ParameterDefinition.cs │ │ │ ├── ParameterDefinitionCollection.cs │ │ │ ├── ParameterReference.cs │ │ │ ├── PinnedType.cs │ │ │ ├── PointerType.cs │ │ │ ├── PropertyAttributes.cs │ │ │ ├── PropertyDefinition.cs │ │ │ ├── PropertyReference.cs │ │ │ ├── ReferenceType.cs │ │ │ ├── Resource.cs │ │ │ ├── SecurityDeclaration.cs │ │ │ ├── SentinelType.cs │ │ │ ├── TargetRuntime.cs │ │ │ ├── TypeAttributes.cs │ │ │ ├── TypeDefinition.cs │ │ │ ├── TypeDefinitionCollection.cs │ │ │ ├── TypeParser.cs │ │ │ ├── TypeReference.cs │ │ │ ├── TypeSpecification.cs │ │ │ ├── TypeSystem.cs │ │ │ └── VariantType.cs │ │ ├── Mono.Cecil.Cil/ │ │ │ ├── Code.cs │ │ │ ├── CodeReader.cs │ │ │ ├── CodeWriter.cs │ │ │ ├── Document.cs │ │ │ ├── ExceptionHandler.cs │ │ │ ├── ILProcessor.cs │ │ │ ├── Instruction.cs │ │ │ ├── MethodBody.cs │ │ │ ├── OpCode.cs │ │ │ ├── OpCodes.cs │ │ │ ├── SequencePoint.cs │ │ │ ├── Symbols.cs │ │ │ ├── VariableDefinition.cs │ │ │ └── VariableReference.cs │ │ ├── Mono.Cecil.Metadata/ │ │ │ ├── BlobHeap.cs │ │ │ ├── Buffers.cs │ │ │ ├── CodedIndex.cs │ │ │ ├── ElementType.cs │ │ │ ├── GuidHeap.cs │ │ │ ├── Heap.cs │ │ │ ├── MetadataToken.cs │ │ │ ├── Row.cs │ │ │ ├── StringHeap.cs │ │ │ ├── TableHeap.cs │ │ │ ├── TokenType.cs │ │ │ ├── UserStringHeap.cs │ │ │ └── Utilities.cs │ │ ├── Mono.Cecil.PE/ │ │ │ ├── BinaryStreamReader.cs │ │ │ ├── BinaryStreamWriter.cs │ │ │ ├── ByteBuffer.cs │ │ │ ├── ByteBufferEqualityComparer.cs │ │ │ ├── DataDirectory.cs │ │ │ ├── Image.cs │ │ │ ├── ImageReader.cs │ │ │ ├── ImageWriter.cs │ │ │ ├── Section.cs │ │ │ └── TextMap.cs │ │ ├── Mono.Collections.Generic/ │ │ │ ├── Collection.cs │ │ │ └── ReadOnlyCollection.cs │ │ └── Mono.Security.Cryptography/ │ │ ├── CryptoConvert.cs │ │ └── CryptoService.cs │ ├── Properties/ │ │ └── AssemblyInfo.cs │ ├── SGFUnity.csproj │ ├── SGFUnity.csproj.user │ ├── UI/ │ │ ├── Drag/ │ │ │ ├── Draggable.cs │ │ │ └── DropZone.cs │ │ ├── SGUI/ │ │ │ ├── Drawing.cs │ │ │ ├── DrawingSimple.cs │ │ │ └── GUICurve.cs │ │ ├── UIDefine.cs │ │ ├── UIElementBinder.cs │ │ ├── UIEventTrigger.cs │ │ ├── UILib/ │ │ │ ├── Control/ │ │ │ │ ├── CtlList.cs │ │ │ │ ├── CtlListItem.cs │ │ │ │ ├── CtlProgressBar.cs │ │ │ │ └── UIControl.cs │ │ │ ├── UIMsgBox.cs │ │ │ ├── UIMsgTips.cs │ │ │ └── UISimpleLoading.cs │ │ ├── UILoading.cs │ │ ├── UIManager.cs │ │ ├── UIPage.cs │ │ ├── UIPanel.cs │ │ ├── UIRes.cs │ │ ├── UIRoot.cs │ │ ├── UIUtils.cs │ │ ├── UIWidget.cs │ │ └── UIWindow.cs │ └── Utils/ │ ├── GameObjectUtils.cs │ ├── NetUtils.cs │ └── QRCodeUtils.cs └── SGFUnityTest/ ├── Properties/ │ └── AssemblyInfo.cs ├── SGFUnityTest.csproj └── UnitTest1.cs ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ .vs *.pdb *.mdb SGFAppCommon/obj SGFAppDemo/obj SGFAppILRScript/obj SGFCore/obj SGFDebuger/obj SGFServerLite/obj SGFUnity/obj ================================================ FILE: Apps/DirConfig.json ================================================ DB,4.3.2.1,32154 DB,4.3.2.1,32153 Zone,5.3.2.1,32154 ================================================ FILE: Apps/ILRuntime.dll.config ================================================ ================================================ FILE: Apps/SGFAppDemo.exe.config ================================================ ================================================ FILE: Apps/SGFAppILRScript.dll.config ================================================ ================================================ FILE: Apps/SGFCore.dll.config ================================================ ================================================ FILE: Apps/SGFCore.xml ================================================ SGFCore 序列化帮助类 序列化pb数据 反序列化pb数据 获取Type所指定的ModuleEvent(它其实是一个EventTable) 如果不存在,则实例化一个 采用线性同余算法产生一个0~1之间的随机小数 实现抽象事件功能 可以像这样使用:obj.Event("onLogin").AddListener(...) 事件的发送方法:this.Event("onLogin").Invoke(args) 而不需要在编码时先定义好,以提高模块的抽象程度 但是在模块内部的类不应该过于抽象,比如数据发生更新了, 在UI类这样使用:obj.onUpdate.AddListener(...) 这两种方法在使用形式上,保持了一致性! 调用它以创建模块 调用它以释放模块 当模块收到消息后,对消息进行一些处理 由派生类去实现,用于处理消息 显示业务模块的主UI 一般业务模块都有UI,这是游戏业务模块的特点 构造函数传入Name 是因为Lua模块无法通过反射来获取Name 这里应该去加载Lua脚本 并且将EventManager映射到Lua脚本中 调用它以卸载Lua脚本 调用它以释放模块 已创建的模块列表 当目标模块未创建时,缓存的消息对象 当目标模块未创建时,预监听的事件 用于模块反射的域 初始化 业务模块所在的域 通过类型创建一个业务模块 通过名字创建一个业务模块 先通过名字反射出Class,如果不存在 则通过扫描Lua文件目录加载LuaModule 业务模块的名字 释放一个由ModuleManager创建的模块 遵守谁创建谁释放的原则 释放所有模块 通过名字获取一个Module 如果未创建过该Module,则返回null 显示业务模块的默认UI 向指定的模块发送消息 监听指定模块的指定事件 用于实现单例 调用它以创建模块 并且检查它是否以单例形式创建 临时字节长度 去掉已经读完的字节 装POSITION设置成0 将位置设置到最大 将Byte[]写入Buffer的末尾 不移动游标,返回长度 把src对象的数组copy到本对象,从dstOffect的地方开始 不移动游标,返回长度 把src对象的数组从srcOffset开始copy到本对象从dstOffect的地方开始 不移动游标,返回长度 从指定Pos增加指定Len 读取数据 字节读出 字节写入... 设置帧数据的监听 监听来自FSPClient的帧数据 由外界驱动 执行每一帧 给外界用来发送FSPVkey的 用于本地兼容,比如打PVE的时候,也可以用帧同步兼容 0 初始状态 游戏创建状态 只有在该状态下,才允许加入玩家 当所有玩家都发VKey.GameBegin后,进入下一个状态 游戏开始状态 在该状态下,等待所有玩家发VKey.RoundBegin,或者 判断玩家是否掉线 当所有人都发送VKey.RoundBegin,进入下一个状态 当有玩家掉线,则从FSPGame中删除该玩家: 判断如果只剩下1个玩家了,则直接进入GameEnd状态,否则不影响游戏状态 回合开始状态 (这个时候客户端可能在加载资源) 在该状态下,等待所有玩家发VKey.ControlStart, 或者 判断玩家是否掉线 当所有人都发送VKey.ControlStart,进入下一个状态 当有玩家掉线,则从FSPGame中删除该玩家: 判断如果只剩下1个玩家了,则直接进入GameEnd状态,否则不影响游戏状态 可以开始操作状态 (因为每个回合可能都会有加载过程,不同的玩家加载速度可能不同,需要用一个状态统一一下) 在该状态下,接收玩家的业务VKey, 或者 VKey.RoundEnd,或者VKey.GameExit 当所有人都发送VKey.RoundEnd,进入下一个状态 当有玩家掉线,或者发送VKey.GameExit,则从FSPGame中删除该玩家: 判断如果只剩下1个玩家了,则直接进入GameEnd状态,否则不影响游戏状态 回合结束状态 (大部分游戏只有1个回合,也有些游戏有多个回合,由客户端逻辑决定) 在该状态下,等待玩家发送VKey.GameEnd,或者 VKey.RoundBegin(如果游戏不只1个回合的话) 当所有人都发送VKey.GameEnd,或者 VKey.RoundBegin时,进入下一个状态 当有玩家掉线,则从FSPGame中删除该玩家: 判断如果只剩下1个玩家了,则直接进入GameEnd状态,否则不影响游戏状态 游戏结束状态 在该状态下,不再接收任何Vkey,然后给所有玩家发VKey.GameEnd,并且等待FSPServer关闭 为了兼容键盘和轮盘操作,将玩家的操作抽象为【虚拟按键+参数】的【命令】形式:VKey+Arg 键值 参数列表 S2C 服务器下发PlayerId C2S 客户端上报ClientFrameId PVP战斗结束 对局开始 开始加载 加载进度条 可以开始控制... 发送中途退出 对局结束 PVP战斗结束 UDP身份字段 PING 响应回包... 最大支持的玩家数:31 因为用来保存玩家Flag的Int只有31位有效位可用,不过31已经足够了 处理来自客户端的 Cmd 对其中的关键VKey进行处理 并且收集业务VKey 驱动游戏状态 检测游戏是否异常结束 游戏创建状态 只有在该状态下,才允许加入玩家 当所有玩家都发VKey.GameBegin后,进入下一个状态 游戏开始状态 在该状态下,等待所有玩家发VKey.RoundBegin,或者 判断玩家是否掉线 当所有人都发送VKey.RoundBegin,进入下一个状态 当有玩家掉线,则从FSPGame中删除该玩家: 判断如果只剩下1个玩家了,则直接进入GameEnd状态,否则不影响游戏状态 回合开始状态 (这个时候客户端可能在加载资源) 在该状态下,等待所有玩家发VKey.ControlStart, 或者 判断玩家是否掉线 当所有人都发送VKey.ControlStart,进入下一个状态 当有玩家掉线,则从FSPGame中删除该玩家: 判断如果只剩下1个玩家了,则直接进入GameEnd状态,否则不影响游戏状态 可以开始操作状态 (因为每个回合可能都会有加载过程,不同的玩家加载速度可能不同,需要用一个状态统一一下) 在该状态下,接收玩家的业务VKey, 或者 VKey.RoundEnd,或者VKey.GameExit 当所有人都发送VKey.RoundEnd,进入下一个状态 当有玩家掉线,或者发送VKey.GameExit,则从FSPGame中删除该玩家: 判断如果只剩下1个玩家了,则直接进入GameEnd状态,否则不影响游戏状态 回合结束状态 (大部分游戏只有1个回合,也有些游戏有多个回合,由客户端逻辑决定) 在该状态下,等待玩家发送VKey.GameEnd,或者 VKey.RoundBegin(如果游戏不只1个回合的话) 当所有人都发送VKey.GameEnd,或者 VKey.RoundBegin时,进入下一个状态 当有玩家掉线,则从FSPGame中删除该玩家: 判断如果只剩下1个玩家了,则直接进入GameEnd状态,否则不影响游戏状态 判断是否掉线 帧间隔... 如果不显示天, 显示hh就会显示所有小时, 但是又怕有地方需要这样, 因此这里新开一下 This class encodes and decodes JSON strings. Spec. details, see http://www.json.org/ JSON uses Arrays and Objects. These correspond here to the datatypes IList and IDictionary. All numbers are parsed to doubles. Parses the string json into a value A JSON string. An List<object>, a Dictionary<string, object>, a double, an integer,a string, null, true, or false Converts a IDictionary / IList object or a simple type (string, int, etc.) into a JSON string A Dictionary<string, object> / List<object> A JSON encoded string, or null if object 'json' is not serializable Returns all elements of the source which are of FilterType. 移除不符合条件的元素 返回容器是否为空 批量追加元素 将容器序列化成字符串 格式:{a, b, c} 将容器序列化成字符串 Returns an enumerable of all elements of the given list but the first, keeping them in order. Returns an enumarable of all elements in the given list but the last, keeping them in order. 根据给定的方法,求出容器中最大的元素 Finds the maximum element in the source as scored by the given function. Returns a enumerable with elements in order, but the first element is moved to the end. Returns a enumerable with elements in order, but the last element is moved to the front. Returns a random element from the list. Returns a random sample from the list. 乱序 Find an element in a collection by binary searching. This requires the collection to be sorted on the values returned by getSubElement This will compare some derived property of the elements in the collection, rather than the elements themselves. Find an element in a collection by binary searching. This requires the collection to be sorted on the values returned by getSubElement This will compare some derived property of the elements in the collection, rather than the elements themselves. Find an element in a collection by binary searching. This requires the collection to be sorted on the values returned by getSubElement This will compare some derived property of the elements in the collection, rather than the elements themselves. Find an element in a collection by binary searching. This requires the collection to be sorted on the values returned by getSubElement This will compare some derived property of the elements in the collection, rather than the elements themselves. 对象如果为Null,抛出异常 异常消息 ================================================ FILE: Apps/SGFServer.exe.config ================================================ ================================================ FILE: Apps/SGFServerDemo.exe.config ================================================ ================================================ FILE: ILRuntime/App.config ================================================ ================================================ FILE: ILRuntime/ILRuntime/Adapters/Editor/ILRuntimeCLRBinding.cs ================================================ #if UNITY_EDITOR using UnityEditor; using UnityEngine; using System; using System.Text; using System.Collections.Generic; using OT.Foundation; [System.Reflection.Obfuscation(Exclude = true)] public class ILRuntimeCLRBinding { [MenuItem("ILRuntime/Generate CLR Binding Code")] static void GenerateCLRBinding() { List types = new List(); types.Add(typeof(int)); types.Add(typeof(float)); types.Add(typeof(long)); types.Add(typeof(object)); types.Add(typeof(string)); types.Add(typeof(Array)); types.Add(typeof(Vector2)); types.Add(typeof(Vector3)); types.Add(typeof(Quaternion)); types.Add(typeof(GameObject)); types.Add(typeof(UnityEngine.Object)); types.Add(typeof(Transform)); types.Add(typeof(RectTransform)); types.Add(typeof(CLRBindingTestClass)); types.Add(typeof(Time)); types.Add(typeof(Debug)); types.Add(typeof(OT.Foundation.Debuger)); //所有DLL内的类型的真实C#类型都是ILTypeInstance types.Add(typeof(List)); ILRuntime.Runtime.CLRBinding.BindingCodeGenerator.GenerateBindingCode(types, "Assets/ILRuntime/Generated"); } [MenuItem("ILRuntime/Generate CLR Binding Code by Analysis")] static void GenerateCLRBindingByAnalysis() { //用新的分析热更dll调用引用来生成绑定代码 ILRuntime.Runtime.Enviorment.AppDomain domain = new ILRuntime.Runtime.Enviorment.AppDomain(); using (System.IO.FileStream fs = new System.IO.FileStream("Assets/StreamingAssets/HotFix_Project.dll", System.IO.FileMode.Open, System.IO.FileAccess.Read)) { domain.LoadAssembly(fs); } //Crossbind Adapter is needed to generate the correct binding code InitILRuntime(domain); ILRuntime.Runtime.CLRBinding.BindingCodeGenerator.GenerateBindingCode(domain, "Assets/ILRuntime/Generated"); } static void InitILRuntime(ILRuntime.Runtime.Enviorment.AppDomain domain) { //这里需要注册所有热更DLL中用到的跨域继承Adapter,否则无法正确抓取引用 domain.RegisterCrossBindingAdaptor(new MonoBehaviourAdapter()); domain.RegisterCrossBindingAdaptor(new CoroutineAdapter()); domain.RegisterCrossBindingAdaptor(new InheritanceAdapter()); } } #endif ================================================ FILE: ILRuntime/ILRuntime/CLR/Method/CLRMethod.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using Mono.Cecil; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Enviorment; using ILRuntime.CLR.TypeSystem; using ILRuntime.Runtime.Stack; using ILRuntime.CLR.Utils; namespace ILRuntime.CLR.Method { public class CLRMethod : IMethod { MethodInfo def; ConstructorInfo cDef; List parameters; ILRuntime.Runtime.Enviorment.AppDomain appdomain; CLRType declaringType; ParameterInfo[] param; bool isConstructor; CLRRedirectionDelegate redirect; IType[] genericArguments; object[] invocationParam; bool isDelegateInvoke; int hashCode = -1; static int instance_id = 0x20000000; public IType DeclearingType { get { return declaringType; } } public string Name { get { return def.Name; } } public bool HasThis { get { return isConstructor ? !cDef.IsStatic : !def.IsStatic; } } public int GenericParameterCount { get { if (def.ContainsGenericParameters && def.IsGenericMethodDefinition) { return def.GetGenericArguments().Length; } return 0; } } public bool IsGenericInstance { get { return genericArguments != null; } } public bool IsDelegateInvoke { get { return isDelegateInvoke; } } public bool IsStatic { get { return def.IsStatic; } } public CLRRedirectionDelegate Redirection { get { return redirect; } } public MethodInfo MethodInfo { get { return def; } } public ConstructorInfo ConstructorInfo { get { return cDef; } } public IType[] GenericArguments { get { return genericArguments; } } internal CLRMethod(MethodInfo def, CLRType type, ILRuntime.Runtime.Enviorment.AppDomain domain) { this.def = def; declaringType = type; this.appdomain = domain; param = def.GetParameters(); if (!def.ContainsGenericParameters) { ReturnType = domain.GetType(def.ReturnType.FullName); if (ReturnType == null) { ReturnType = domain.GetType(def.ReturnType.AssemblyQualifiedName); } } if (type.IsDelegate && def.Name == "Invoke") isDelegateInvoke = true; isConstructor = false; if (def != null) { if (def.IsGenericMethod && !def.IsGenericMethodDefinition) { appdomain.RedirectMap.TryGetValue(def.GetGenericMethodDefinition(), out redirect); } else appdomain.RedirectMap.TryGetValue(def, out redirect); } } internal CLRMethod(ConstructorInfo def, CLRType type, ILRuntime.Runtime.Enviorment.AppDomain domain) { this.cDef = def; declaringType = type; this.appdomain = domain; param = def.GetParameters(); if (!def.ContainsGenericParameters) { ReturnType = type; } isConstructor = true; if (def != null) { appdomain.RedirectMap.TryGetValue(cDef, out redirect); } } public int ParameterCount { get { return param != null ? param.Length : 0; } } public List Parameters { get { if (parameters == null) { InitParameters(); } return parameters; } } public IType ReturnType { get; private set; } public bool IsConstructor { get { return cDef != null; } } void InitParameters() { parameters = new List(); foreach (var i in param) { IType type = appdomain.GetType(i.ParameterType.FullName); if (type == null) type = appdomain.GetType(i.ParameterType.AssemblyQualifiedName); if (i.ParameterType.IsGenericTypeDefinition) { if (type == null) type = appdomain.GetType(i.ParameterType.GetGenericTypeDefinition().FullName); if (type == null) type = appdomain.GetType(i.ParameterType.GetGenericTypeDefinition().AssemblyQualifiedName); } if (i.ParameterType.ContainsGenericParameters) { var t = i.ParameterType; if (t.HasElementType) t = i.ParameterType.GetElementType(); else if (t.GetGenericArguments().Length > 0) { t = t.GetGenericArguments()[0]; } type = new ILGenericParameterType(t.Name); } if (type == null) throw new TypeLoadException(); parameters.Add(type); } } unsafe StackObject* Minus(StackObject* a, int b) { return (StackObject*)((long)a - sizeof(StackObject) * b); } public unsafe object Invoke(Runtime.Intepreter.ILIntepreter intepreter, StackObject* esp, IList mStack, bool isNewObj = false) { if (parameters == null) { InitParameters(); } int paramCount = ParameterCount; if (invocationParam == null) invocationParam = new object[paramCount]; object[] param = invocationParam; for (int i = paramCount; i >= 1; i--) { var p = Minus(esp, i); var obj = this.param[paramCount - i].ParameterType.CheckCLRTypes(StackObject.ToObject(p, appdomain, mStack)); obj = ILIntepreter.CheckAndCloneValueType(obj, appdomain); param[paramCount - i] = obj; } if (isConstructor) { if (!isNewObj) { if (!cDef.IsStatic) { object instance = declaringType.TypeForCLR.CheckCLRTypes(StackObject.ToObject((Minus(esp, paramCount + 1)), appdomain, mStack)); if (instance == null) throw new NullReferenceException(); if (instance is CrossBindingAdaptorType && paramCount == 0)//It makes no sense to call the Adaptor's default constructor return null; cDef.Invoke(instance, param); return null; } else { throw new NotImplementedException(); } } else { var res = cDef.Invoke(param); FixReference(paramCount, esp, param, mStack); return res; } } else { object instance = null; if (!def.IsStatic) { instance = declaringType.TypeForCLR.CheckCLRTypes(StackObject.ToObject((Minus(esp, paramCount + 1)), appdomain, mStack)); if (instance == null) throw new NullReferenceException(); } object res = null; /*if (redirect != null) res = redirect(new ILContext(appdomain, intepreter, esp, mStack, this), instance, param, genericArguments); else*/ { res = def.Invoke(instance, param); } FixReference(paramCount, esp, param, mStack); return res; } } unsafe void FixReference(int paramCount, StackObject* esp, object[] param, IList mStack) { for (int i = paramCount; i >= 1; i--) { var p = Minus(esp, i); var val = param[paramCount - i]; switch (p->ObjectType) { case ObjectTypes.StackObjectReference: { var dst = *(StackObject**)&p->Value; if (dst->ObjectType >= ObjectTypes.Object) { var obj = val; if (obj is CrossBindingAdaptorType) obj = ((CrossBindingAdaptorType)obj).ILInstance; mStack[dst->Value] = obj; } else { ILIntepreter.UnboxObject(dst, val); } } break; case ObjectTypes.FieldReference: { var obj = mStack[p->Value]; if(obj is ILTypeInstance) { ((ILTypeInstance)obj)[p->ValueLow] = val; } else { var t = appdomain.GetType(obj.GetType()) as CLRType; t.GetField(p->ValueLow).SetValue(obj, val); } } break; case ObjectTypes.StaticFieldReference: { var t = appdomain.GetType(p->Value); if(t is ILType) { ((ILType)t).StaticInstance[p->ValueLow] = val; } else { ((CLRType)t).SetStaticFieldValue(p->ValueLow, val); } } break; } } } public IMethod MakeGenericMethod(IType[] genericArguments) { Type[] p = new Type[genericArguments.Length]; for (int i = 0; i < genericArguments.Length; i++) { p[i] = genericArguments[i].TypeForCLR; } var t = def.MakeGenericMethod(p); var res = new CLRMethod(t, declaringType, appdomain); res.genericArguments = genericArguments; return res; } public override string ToString() { if (def != null) return def.ToString(); else return cDef.ToString(); } public override int GetHashCode() { if (hashCode == -1) hashCode = System.Threading.Interlocked.Add(ref instance_id, 1); return hashCode; } } } ================================================ FILE: ILRuntime/ILRuntime/CLR/Method/ExceptionHandler.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.TypeSystem; namespace ILRuntime.CLR.Method { enum ExceptionHandlerType { Catch, Finally, Fault, } class ExceptionHandler { public ExceptionHandlerType HandlerType { get; set; } public int TryStart { get; set; } public int TryEnd { get; set; } public int HandlerStart { get; set; } public int HandlerEnd { get; set; } public IType CatchType { get; set; } } } ================================================ FILE: ILRuntime/ILRuntime/CLR/Method/ILMethod.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using Mono.Cecil; using ILRuntime.Runtime.Intepreter.OpCodes; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Debugger; using ILRuntime.CLR.TypeSystem; using ILRuntime.Reflection; namespace ILRuntime.CLR.Method { public class ILMethod : IMethod { OpCode[] body; MethodDefinition def; List parameters; ILRuntime.Runtime.Enviorment.AppDomain appdomain; ILType declaringType; ExceptionHandler[] exceptionHandler; KeyValuePair[] genericParameters; IType[] genericArguments; Dictionary jumptables; bool isDelegateInvoke; ILRuntimeMethodInfo refletionMethodInfo; ILRuntimeConstructorInfo reflectionCtorInfo; int paramCnt, localVarCnt; Mono.Collections.Generic.Collection variables; int hashCode = -1; static int instance_id = 0x10000000; public MethodDefinition Definition { get { return def; } } public Dictionary JumpTables { get { return jumptables; } } internal IDelegateAdapter DelegateAdapter { get; set; } internal int StartLine { get; set; } internal int EndLine { get; set; } public MethodInfo ReflectionMethodInfo { get { if (IsConstructor) throw new NotSupportedException(); if (refletionMethodInfo == null) refletionMethodInfo = new ILRuntimeMethodInfo(this); return refletionMethodInfo; } } public ConstructorInfo ReflectionConstructorInfo { get { if (!IsConstructor) throw new NotSupportedException(); if (reflectionCtorInfo == null) reflectionCtorInfo = new ILRuntimeConstructorInfo(this); return reflectionCtorInfo; } } internal ExceptionHandler[] ExceptionHandler { get { if (body == null) InitCodeBody(); return exceptionHandler; } } public string Name { get { return def.Name; } } public IType DeclearingType { get { return declaringType; } } public bool HasThis { get { return def.HasThis; } } public int GenericParameterCount { get { if (IsGenericInstance) return 0; return def.GenericParameters.Count; } } public bool IsGenericInstance { get { return genericParameters != null; } } public Mono.Collections.Generic.Collection Variables { get { return variables; } } public KeyValuePair[] GenericArguments { get { return genericParameters; } } public IType[] GenericArugmentsArray { get { return genericArguments; } } public ILMethod(MethodDefinition def, ILType type, ILRuntime.Runtime.Enviorment.AppDomain domain) { this.def = def; declaringType = type; if (def.ReturnType.IsGenericParameter) { ReturnType = FindGenericArgument(def.ReturnType.Name); } else ReturnType = domain.GetType(def.ReturnType, type, this); if (type.IsDelegate && def.Name == "Invoke") isDelegateInvoke = true; this.appdomain = domain; paramCnt = def.HasParameters ? def.Parameters.Count : 0; #if DEBUG if (def.HasBody) { var sp = DebugService.FindSequencePoint(def.Body.Instructions[0]); if (sp != null) { StartLine = sp.StartLine; sp = DebugService.FindSequencePoint(def.Body.Instructions[def.Body.Instructions.Count - 1]); if (sp != null) { EndLine = sp.EndLine; } } } #endif } public IType FindGenericArgument(string name) { IType res = declaringType.FindGenericArgument(name); if (res == null && genericParameters != null) { foreach (var i in genericParameters) { if (i.Key == name) return i.Value; } } else return res; return null; } internal OpCode[] Body { get { if (body == null) InitCodeBody(); return body; } } public int LocalVariableCount { get { return localVarCnt; } } public bool IsConstructor { get { return def.IsConstructor; } } public bool IsDelegateInvoke { get { return isDelegateInvoke; } } public bool IsStatic { get { return def.IsStatic; } } public int ParameterCount { get { return paramCnt; } } public List Parameters { get { if (def.HasParameters && parameters == null) { InitParameters(); } return parameters; } } public IType ReturnType { get; private set; } void InitCodeBody() { if (def.HasBody) { localVarCnt = def.Body.Variables.Count; body = new OpCode[def.Body.Instructions.Count]; Dictionary addr = new Dictionary(); for (int i = 0; i < body.Length; i++) { var c = def.Body.Instructions[i]; OpCode code = new OpCode(); code.Code = (OpCodeEnum)c.OpCode.Code; addr[c] = i; body[i] = code; } for (int i = 0; i < body.Length; i++) { var c = def.Body.Instructions[i]; InitToken(ref body[i], c.Operand, addr); } for (int i = 0; i < def.Body.ExceptionHandlers.Count; i++) { var eh = def.Body.ExceptionHandlers[i]; if (exceptionHandler == null) exceptionHandler = new Method.ExceptionHandler[def.Body.ExceptionHandlers.Count]; ExceptionHandler e = new ExceptionHandler(); e.HandlerStart = addr[eh.HandlerStart]; e.HandlerEnd = addr[eh.HandlerEnd] - 1; e.TryStart = addr[eh.TryStart]; e.TryEnd = addr[eh.TryEnd] - 1; switch (eh.HandlerType) { case Mono.Cecil.Cil.ExceptionHandlerType.Catch: e.CatchType = appdomain.GetType(eh.CatchType, declaringType, this); e.HandlerType = ExceptionHandlerType.Catch; break; case Mono.Cecil.Cil.ExceptionHandlerType.Finally: e.HandlerType = ExceptionHandlerType.Finally; break; case Mono.Cecil.Cil.ExceptionHandlerType.Fault: e.HandlerType = ExceptionHandlerType.Fault; break; default: throw new NotImplementedException(); } exceptionHandler[i] = e; //Mono.Cecil.Cil.ExceptionHandlerType. } //Release Method body to save memory variables = def.Body.Variables; def.Body = null; } else body = new OpCode[0]; } unsafe void InitToken(ref OpCode code, object token, Dictionary addr) { switch (code.Code) { case OpCodeEnum.Leave: case OpCodeEnum.Leave_S: case OpCodeEnum.Br: case OpCodeEnum.Br_S: case OpCodeEnum.Brtrue: case OpCodeEnum.Brtrue_S: case OpCodeEnum.Brfalse: case OpCodeEnum.Brfalse_S: //比较流程控制 case OpCodeEnum.Beq: case OpCodeEnum.Beq_S: case OpCodeEnum.Bne_Un: case OpCodeEnum.Bne_Un_S: case OpCodeEnum.Bge: case OpCodeEnum.Bge_S: case OpCodeEnum.Bge_Un: case OpCodeEnum.Bge_Un_S: case OpCodeEnum.Bgt: case OpCodeEnum.Bgt_S: case OpCodeEnum.Bgt_Un: case OpCodeEnum.Bgt_Un_S: case OpCodeEnum.Ble: case OpCodeEnum.Ble_S: case OpCodeEnum.Ble_Un: case OpCodeEnum.Ble_Un_S: case OpCodeEnum.Blt: case OpCodeEnum.Blt_S: case OpCodeEnum.Blt_Un: case OpCodeEnum.Blt_Un_S: code.TokenInteger = addr[(Mono.Cecil.Cil.Instruction)token]; break; case OpCodeEnum.Ldc_I4: code.TokenInteger = (int)token; break; case OpCodeEnum.Ldc_I4_S: code.TokenInteger = (sbyte)token; break; case OpCodeEnum.Ldc_I8: code.TokenLong = (long)token; break; case OpCodeEnum.Ldc_R4: { float val = (float)token; code.TokenInteger = *(int*)&val; } break; case OpCodeEnum.Ldc_R8: { double val = (double)token; code.TokenLong = *(long*)&val; } break; case OpCodeEnum.Stloc: case OpCodeEnum.Stloc_S: case OpCodeEnum.Ldloc: case OpCodeEnum.Ldloc_S: case OpCodeEnum.Ldloca: case OpCodeEnum.Ldloca_S: { Mono.Cecil.Cil.VariableDefinition vd = (Mono.Cecil.Cil.VariableDefinition)token; code.TokenInteger = vd.Index; } break; case OpCodeEnum.Ldarg_S: case OpCodeEnum.Ldarg: case OpCodeEnum.Ldarga: case OpCodeEnum.Ldarga_S: case OpCodeEnum.Starg: case OpCodeEnum.Starg_S: { Mono.Cecil.ParameterDefinition vd = (Mono.Cecil.ParameterDefinition)token; code.TokenInteger = vd.Index; if (HasThis) code.TokenInteger++; } break; case OpCodeEnum.Call: case OpCodeEnum.Newobj: case OpCodeEnum.Ldftn: case OpCodeEnum.Ldvirtftn: case OpCodeEnum.Callvirt: { bool invalidToken; var m = appdomain.GetMethod(token, declaringType, this, out invalidToken); if (m != null) { if (invalidToken) code.TokenInteger = m.GetHashCode(); else code.TokenInteger = token.GetHashCode(); } else { //Cannot find method or the method is dummy MethodReference _ref = (MethodReference)token; int paramCnt = _ref.HasParameters ? _ref.Parameters.Count : 0; if (_ref.HasThis) paramCnt++; code.TokenLong = paramCnt; } } break; case OpCodeEnum.Constrained: case OpCodeEnum.Box: case OpCodeEnum.Unbox_Any: case OpCodeEnum.Unbox: case OpCodeEnum.Initobj: case OpCodeEnum.Isinst: case OpCodeEnum.Newarr: case OpCodeEnum.Stobj: case OpCodeEnum.Ldobj: { code.TokenInteger = GetTypeTokenHashCode(token); } break; case OpCodeEnum.Stfld: case OpCodeEnum.Ldfld: case OpCodeEnum.Ldflda: { code.TokenLong = appdomain.GetStaticFieldIndex(token, declaringType, this); } break; case OpCodeEnum.Stsfld: case OpCodeEnum.Ldsfld: case OpCodeEnum.Ldsflda: { code.TokenLong = appdomain.GetStaticFieldIndex(token, declaringType, this); } break; case OpCodeEnum.Ldstr: { long hashCode = appdomain.CacheString(token); code.TokenLong = hashCode; } break; case OpCodeEnum.Ldtoken: { if (token is FieldReference) { code.TokenInteger = 0; code.TokenLong = appdomain.GetStaticFieldIndex(token, declaringType, this); } else if (token is TypeReference) { code.TokenInteger = 1; code.TokenLong = GetTypeTokenHashCode(token); } else throw new NotImplementedException(); } break; case OpCodeEnum.Switch: { PrepareJumpTable(token, addr); code.TokenInteger = token.GetHashCode(); } break; } } int GetTypeTokenHashCode(object token) { var t = appdomain.GetType(token, declaringType, this); bool isGenericParameter = CheckHasGenericParamter(token); if (t == null && isGenericParameter) { t = FindGenericArgument(((TypeReference)token).Name); } if (t != null) { if (t is ILType) { if (((ILType)t).TypeReference.HasGenericParameters) return t.GetHashCode(); else return ((ILType)t).TypeReference.GetHashCode(); } else if (isGenericParameter) { return t.GetHashCode(); } else return token.GetHashCode(); } return 0; } bool CheckHasGenericParamter(object token) { if (token is TypeReference) { TypeReference _ref = ((TypeReference)token); if (_ref.IsGenericParameter) return true; if (_ref.IsGenericInstance) { GenericInstanceType gi = (GenericInstanceType)_ref; foreach(var i in gi.GenericArguments) { if (CheckHasGenericParamter(i)) return true; } return false; } else return false; } else return false; } void PrepareJumpTable(object token, Dictionary addr) { int hashCode = token.GetHashCode(); if (jumptables == null) jumptables = new Dictionary(); if (jumptables.ContainsKey(hashCode)) return; Mono.Cecil.Cil.Instruction[] e = token as Mono.Cecil.Cil.Instruction[]; int[] addrs = new int[e.Length]; for (int i = 0; i < e.Length; i++) { addrs[i] = addr[e[i]]; } jumptables[hashCode] = addrs; } void InitParameters() { parameters = new List(); foreach (var i in def.Parameters) { IType type = null; bool isByRef = false; bool isArray = false; TypeReference pt = i.ParameterType; if (i.ParameterType.IsByReference) { isByRef = true; pt = pt.GetElementType(); } if (i.ParameterType.IsArray) { isArray = true; pt = pt.GetElementType(); } if (pt.IsGenericParameter) { type = FindGenericArgument(pt.Name); if (type == null && def.HasGenericParameters) { bool found = false; foreach (var j in def.GenericParameters) { if (j.Name == pt.Name) { found = true; break; } } if (found) { type = new ILGenericParameterType(pt.Name); } else throw new NotSupportedException("Cannot find Generic Parameter " + pt.Name + " in " + def.FullName); } if (isByRef) type = type.MakeByRefType(); if (isArray) type = type.MakeArrayType(); } else type = appdomain.GetType(i.ParameterType, declaringType, this); parameters.Add(type); } } public IMethod MakeGenericMethod(IType[] genericArguments) { KeyValuePair[] genericParameters = new KeyValuePair[genericArguments.Length]; for (int i = 0; i < genericArguments.Length; i++) { string name = def.GenericParameters[i].Name; IType val = genericArguments[i]; genericParameters[i] = new KeyValuePair(name, val); } ILMethod m = new ILMethod(def, declaringType, appdomain); m.genericParameters = genericParameters; m.genericArguments = genericArguments; if (m.def.ReturnType.IsGenericParameter) { m.ReturnType = m.FindGenericArgument(m.def.ReturnType.Name); } return m; } public override string ToString() { StringBuilder sb = new StringBuilder(); sb.Append(declaringType.FullName); sb.Append('.'); sb.Append(Name); sb.Append('('); bool isFirst = true; if (parameters == null) InitParameters(); for (int i = 0; i < parameters.Count; i++) { if (isFirst) isFirst = false; else sb.Append(", "); sb.Append(parameters[i].Name); sb.Append(' '); sb.Append(def.Parameters[i].Name); } sb.Append(')'); return sb.ToString(); } public override int GetHashCode() { if (hashCode == -1) hashCode = System.Threading.Interlocked.Add(ref instance_id, 1); return hashCode; } } } ================================================ FILE: ILRuntime/ILRuntime/CLR/Method/IMethod.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.TypeSystem; namespace ILRuntime.CLR.Method { public interface IMethod { string Name { get; } int ParameterCount { get; } bool HasThis { get; } IType DeclearingType { get; } IType ReturnType { get; } List Parameters { get; } int GenericParameterCount { get; } bool IsGenericInstance { get; } bool IsConstructor { get; } bool IsDelegateInvoke { get; } bool IsStatic { get; } IMethod MakeGenericMethod(IType[] genericArguments); } } ================================================ FILE: ILRuntime/ILRuntime/CLR/TypeSystem/CLRType.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using Mono.Cecil; using ILRuntime.CLR.Method; using ILRuntime.Reflection; using ILRuntime.Runtime.Enviorment; namespace ILRuntime.CLR.TypeSystem { public class CLRType : IType { Type clrType; bool isPrimitive, isValueType; Dictionary> methods; ILRuntime.Runtime.Enviorment.AppDomain appdomain; List constructors; KeyValuePair[] genericArguments; List genericInstances; Dictionary fieldMapping; Dictionary fieldInfoCache; Dictionary fieldGetterCache; Dictionary fieldSetterCache; Dictionary fieldIdxMapping; IType[] orderedFieldTypes; CLRMemberwiseCloneDelegate memberwiseCloneDelegate; CLRCreateDefaultInstanceDelegate createDefaultInstanceDelegate; CLRCreateArrayInstanceDelegate createArrayInstanceDelegate; Dictionary fieldTokenMapping; IType byRefType, arrayType, elementType; IType[] interfaces; bool isDelegate; IType baseType; bool isBaseTypeInitialized = false, interfaceInitialized = false, valueTypeBinderGot = false; ILRuntimeWrapperType wraperType; ValueTypeBinder valueTypeBinder; int hashCode = -1; static int instance_id = 0x20000000; public Dictionary Fields { get { if (fieldMapping == null) InitializeFields(); return fieldInfoCache; } } public Dictionary FieldIndexMapping { get { return fieldIdxMapping; } } public IType[] OrderedFieldTypes { get { if (fieldMapping == null) InitializeFields(); return orderedFieldTypes; } } public int TotalFieldCount { get { if (fieldMapping == null) InitializeFields(); return fieldIdxMapping.Count; } } public ILRuntime.Runtime.Enviorment.AppDomain AppDomain { get { return appdomain; } } public CLRType(Type clrType, Runtime.Enviorment.AppDomain appdomain) { this.clrType = clrType; this.appdomain = appdomain; isPrimitive = clrType.IsPrimitive; isValueType = clrType.IsValueType; isDelegate = clrType.BaseType == typeof(MulticastDelegate); } public bool IsGenericInstance { get { return genericArguments != null; } } public KeyValuePair[] GenericArguments { get { return genericArguments; } } public IType ElementType { get { return elementType; } } public bool HasGenericParameter { get { return clrType.ContainsGenericParameters; } } public Type TypeForCLR { get { return clrType; } } public Type ReflectionType { get { if (wraperType == null) wraperType = new ILRuntimeWrapperType(this); return wraperType; } } public IType ByRefType { get { return byRefType; } } public IType ArrayType { get { return arrayType; } } public bool IsArray { get;private set; } public bool IsValueType { get { return isValueType; } } public bool IsDelegate { get { return isDelegate; } } public bool IsPrimitive { get { return isPrimitive; } } public string FullName { get { return clrType.FullName; } } public string Name { get { return clrType.Name; } } public IType BaseType { get { if (!isBaseTypeInitialized) InitializeBaseType(); return baseType; } } public IType[] Implements { get { if (!interfaceInitialized) InitializeInterfaces(); return interfaces; } } public ValueTypeBinder ValueTypeBinder { get { if (clrType.IsValueType) { if (!valueTypeBinderGot) { valueTypeBinderGot = true; if (appdomain.ValueTypeBinders.TryGetValue(clrType, out valueTypeBinder)) valueTypeBinder.CLRType = this; } return valueTypeBinder; } else return null; } } public object PerformMemberwiseClone(object target) { if (memberwiseCloneDelegate == null) { if (!AppDomain.MemberwiseCloneMap.TryGetValue(this.clrType, out memberwiseCloneDelegate)) { var memberwiseClone = clrType.GetMethod("MemberwiseClone", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); if (memberwiseClone != null) { memberwiseCloneDelegate = (ref object t) => memberwiseClone.Invoke(t, null); } else { throw new InvalidOperationException("Memberwise clone method not found for " + clrType.FullName); } } } return memberwiseCloneDelegate(ref target); } void InitializeBaseType() { baseType = appdomain.GetType(clrType.BaseType); if (baseType.TypeForCLR == typeof(Enum) || baseType.TypeForCLR == typeof(object) || baseType.TypeForCLR == typeof(ValueType) || baseType.TypeForCLR == typeof(System.Enum)) {//都是这样,无所谓 baseType = null; } isBaseTypeInitialized = true; } void InitializeInterfaces() { interfaceInitialized = true; var arr = clrType.GetInterfaces(); if (arr.Length >0) { interfaces = new IType[arr.Length]; for (int i = 0; i < interfaces.Length; i++) { interfaces[i] = appdomain.GetType(arr[i]); } } } public object GetFieldValue(int hash, object target) { if (fieldMapping == null) InitializeFields(); var getter = GetFieldGetter(hash); if (getter != null) { return getter(ref target); } var fieldinfo = GetField(hash); if (fieldinfo != null) { return fieldinfo.GetValue(target); } return null; } public void SetStaticFieldValue(int hash, object value) { if (fieldMapping == null) InitializeFields(); var setter = GetFieldSetter(hash); object target = null; if (setter != null) { setter(ref target, value); return; } var fieldInfo = GetField(hash); if (fieldInfo != null) { fieldInfo.SetValue(null, value); } } public unsafe void SetFieldValue(int hash, ref object target, object value) { if (fieldMapping == null) InitializeFields(); var setter = GetFieldSetter(hash); if (setter != null) { setter(ref target, value); return; } var fieldInfo = GetField(hash); if (fieldInfo != null) { fieldInfo.SetValue(target, value); } } private CLRFieldGetterDelegate GetFieldGetter(int hash) { var dic = fieldGetterCache; CLRFieldGetterDelegate res; if (dic != null && dic.TryGetValue(hash, out res)) return res; else if (BaseType != null) return ((CLRType)BaseType).GetFieldGetter(hash); else return null; } private CLRFieldSetterDelegate GetFieldSetter(int hash) { var dic = fieldSetterCache; CLRFieldSetterDelegate res; if (dic != null && dic.TryGetValue(hash, out res)) return res; else if (BaseType != null) return ((CLRType)BaseType).GetFieldSetter(hash); else return null; } public FieldInfo GetField(int hash) { var dic = Fields; FieldInfo res; if (dic.TryGetValue(hash, out res)) return res; else if (BaseType != null) return ((CLRType)BaseType).GetField(hash); else return null; } void InitializeMethods() { methods = new Dictionary>(); constructors = new List(); foreach (var i in clrType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) { if (i.IsPrivate) continue; List lst; if (!methods.TryGetValue(i.Name, out lst)) { lst = new List(); methods[i.Name] = lst; } lst.Add(new CLRMethod(i, this, appdomain)); } foreach (var i in clrType.GetConstructors()) { constructors.Add(new CLRMethod(i, this, appdomain)); } } public List GetMethods() { if (methods == null) InitializeMethods(); List res = new List(); foreach (var i in methods) { foreach (var j in i.Value) res.Add(j); } return res; } public IMethod GetVirtualMethod(IMethod method) { var m = GetMethod(method.Name, method.Parameters, null, method.ReturnType); if (m == null) { return method; } else return m; } void InitializeFields() { fieldMapping = new Dictionary(); fieldInfoCache = new Dictionary(); var fields = clrType.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static); int idx = 0; bool hasValueTypeBinder = ValueTypeBinder != null; if (hasValueTypeBinder) { fieldIdxMapping = new Dictionary(); orderedFieldTypes = new IType[fields.Length]; } foreach (var i in fields) { int hashCode = i.GetHashCode(); if (i.IsPublic || i.IsFamily || hasValueTypeBinder) { fieldMapping[i.Name] = hashCode; fieldInfoCache[hashCode] = i; } if (hasValueTypeBinder && !i.IsStatic) { orderedFieldTypes[idx] = appdomain.GetType(i.FieldType); fieldIdxMapping[hashCode] = idx++; } CLRFieldGetterDelegate getter; if (AppDomain.FieldGetterMap.TryGetValue(i, out getter)) { if (fieldGetterCache == null) fieldGetterCache = new Dictionary(); fieldGetterCache[hashCode] = getter; } CLRFieldSetterDelegate setter; if (AppDomain.FieldSetterMap.TryGetValue(i, out setter)) { if (fieldSetterCache == null) fieldSetterCache = new Dictionary(); fieldSetterCache[hashCode] = setter; } } } public int GetFieldIndex(object token) { if (fieldMapping == null) InitializeFields(); int idx; int hashCode = token.GetHashCode(); if (fieldTokenMapping == null) fieldTokenMapping = new Dictionary(); if (fieldTokenMapping.TryGetValue(hashCode, out idx)) return idx; FieldReference f = token as FieldReference; if (fieldMapping.TryGetValue(f.Name, out idx)) { fieldTokenMapping[hashCode] = idx; return idx; } return -1; } public IType FindGenericArgument(string key) { if (genericArguments != null) { foreach (var i in genericArguments) { if (i.Key == key) return i.Value; } } return null; } public IMethod GetMethod(string name, int paramCount, bool declaredOnly = false) { if (methods == null) InitializeMethods(); List lst; if (methods.TryGetValue(name, out lst)) { foreach (var i in lst) { if (i.ParameterCount == paramCount) return i; } } return null; } public IMethod GetMethod(string name, List param, IType[] genericArguments, IType returnType = null, bool declaredOnly = false) { if (methods == null) InitializeMethods(); List lst; IMethod genericMethod = null; if (methods.TryGetValue(name, out lst)) { foreach (var i in lst) { if (i.ParameterCount == param.Count) { bool match = true; if (genericArguments != null && i.GenericParameterCount == genericArguments.Length) { for (int j = 0; j < param.Count; j++) { var p = i.Parameters[j].TypeForCLR; var q = param[j].TypeForCLR; if (i.Parameters[j].HasGenericParameter) { //TODO should match the generic parameters; continue; } if (q != p) { match = false; break; } } if (match && genericMethod == null) { genericMethod = i; } } else { if (genericArguments == null) match = i.GenericArguments == null; else { if (i.GenericArguments == null) match = false; else match = i.GenericArguments.Length == genericArguments.Length; } for (int j = 0; j < param.Count; j++) { var typeA = param[j].TypeForCLR.IsByRef ? param[j].TypeForCLR.GetElementType() : param[j].TypeForCLR; var typeB = i.Parameters[j].TypeForCLR.IsByRef ? i.Parameters[j].TypeForCLR.GetElementType() : i.Parameters[j].TypeForCLR; if (typeA != typeB) { match = false; break; } } if (match) { match = returnType == null || i.ReturnType.TypeForCLR == returnType.TypeForCLR; } if (match) { if (i.IsGenericInstance) { if (i.GenericArguments.Length == genericArguments.Length) { for (int j = 0; j < genericArguments.Length; j++) { if (i.GenericArguments[j] != genericArguments[j]) { match = false; break; } } if (match) return i; } } else return i; } } } } } if (genericArguments != null && genericMethod != null) { var m = genericMethod.MakeGenericMethod(genericArguments); lst.Add((CLRMethod)m); return m; } return null; } public bool CanAssignTo(IType type) { if (this == type) { return true; } else return false; } public IMethod GetConstructor(List param) { if (constructors == null) InitializeMethods(); foreach (var i in constructors) { if (i.ParameterCount == param.Count) { bool match = true; for (int j = 0; j < param.Count; j++) { if (param[j].TypeForCLR != i.Parameters[j].TypeForCLR) { match = false; break; } } if (match) { return i; } } } return null; } public IType MakeGenericInstance(KeyValuePair[] genericArguments) { if (genericInstances == null) genericInstances = new List(); foreach (var i in genericInstances) { bool match = true; for (int j = 0; j < genericArguments.Length; j++) { if (i.genericArguments[j].Value != genericArguments[j].Value) { match = false; break; } } if (match) return i; } Type[] args = new Type[genericArguments.Length]; for (int i = 0; i < genericArguments.Length; i++) { args[i] = genericArguments[i].Value.TypeForCLR; } Type newType = clrType.MakeGenericType(args); var res = new CLRType(newType, appdomain); res.genericArguments = genericArguments; genericInstances.Add(res); return res; } public object CreateDefaultInstance() { if (createDefaultInstanceDelegate == null) { if (!AppDomain.CreateDefaultInstanceMap.TryGetValue(clrType, out createDefaultInstanceDelegate)) { createDefaultInstanceDelegate = () => Activator.CreateInstance(TypeForCLR); } } return createDefaultInstanceDelegate(); } public object CreateArrayInstance(int size) { if (createArrayInstanceDelegate == null) { if (!AppDomain.CreateArrayInstanceMap.TryGetValue(clrType, out createArrayInstanceDelegate)) { createArrayInstanceDelegate = s => Array.CreateInstance(TypeForCLR, s); } } return createArrayInstanceDelegate(size); } public IType MakeByRefType() { if (byRefType == null) { Type t = clrType.MakeByRefType(); byRefType = new CLRType(t, appdomain); } return byRefType; } public IType MakeArrayType() { if (arrayType == null) { Type t = clrType.MakeArrayType(); arrayType = new CLRType(t, appdomain); ((CLRType)arrayType).elementType = this; ((CLRType)arrayType).IsArray = true; } return arrayType; } public IType ResolveGenericType(IType contextType) { throw new NotImplementedException(); } public override int GetHashCode() { if (hashCode == -1) hashCode = System.Threading.Interlocked.Add(ref instance_id, 1); return hashCode; } public override string ToString() { return clrType.ToString(); } } } ================================================ FILE: ILRuntime/ILRuntime/CLR/TypeSystem/ILGenericParameterType.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.CLR.TypeSystem { class ILGenericParameterType : IType { string name; ILGenericParameterType arrayType; public ILGenericParameterType(string name) { this.name = name; } public bool IsGenericInstance { get { return false; } } public KeyValuePair[] GenericArguments { get { return null; } } public bool HasGenericParameter { get { return true; } } public Type TypeForCLR { get { return typeof(ILGenericParameterType); } } public string FullName { get { return name; } } public Runtime.Enviorment.AppDomain AppDomain { get { return null; } } public Method.IMethod GetMethod(string name, int paramCount, bool declaredOnly = false) { return null; } public Method.IMethod GetMethod(string name, List param, IType[] genericArguments, IType returnType = null, bool declaredOnly = false) { return null; } public List GetMethods() { return null; } public Method.IMethod GetConstructor(List param) { return null; } public bool CanAssignTo(IType type) { return false; } public IType MakeGenericInstance(KeyValuePair[] genericArguments) { return null; } public IType ResolveGenericType(IType contextType) { throw new NotImplementedException(); } public int GetFieldIndex(object token) { return -1; } public IType FindGenericArgument(string key) { return null; } public IType ByRefType { get { throw new NotImplementedException(); } } public IType MakeByRefType() { return this; } public IType ArrayType { get { return arrayType; } } public IType MakeArrayType() { if (arrayType == null) arrayType = new ILGenericParameterType(name + "[]"); return arrayType; } public bool IsValueType { get { throw new NotImplementedException(); } } public bool IsPrimitive { get { return false; } } public string Name { get { return name; } } public bool IsDelegate { get { return false; } } public Type ReflectionType { get { throw new NotImplementedException(); } } public IType BaseType { get { return null; } } public Method.IMethod GetVirtualMethod(Method.IMethod method) { return method; } public bool IsArray { get { return false; } } public IType[] Implements { get { return null; } } } } ================================================ FILE: ILRuntime/ILRuntime/CLR/TypeSystem/ILType.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using Mono.Cecil; using ILRuntime.Runtime.Enviorment; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Intepreter; using ILRuntime.Reflection; namespace ILRuntime.CLR.TypeSystem { public class ILType : IType { Dictionary> methods; TypeReference typeRef; TypeDefinition definition; ILRuntime.Runtime.Enviorment.AppDomain appdomain; ILMethod staticConstructor; List constructors; IType[] fieldTypes; FieldDefinition[] fieldDefinitions; IType[] staticFieldTypes; FieldDefinition[] staticFieldDefinitions; Dictionary fieldMapping; Dictionary staticFieldMapping; ILTypeStaticInstance staticInstance; Dictionary fieldTokenMapping = new Dictionary(); int fieldStartIdx = -1; int totalFieldCnt = -1; KeyValuePair[] genericArguments; IType baseType, byRefType, arrayType, enumType, elementType; Type arrayCLRType, byRefCLRType; IType[] interfaces; bool baseTypeInitialized = false; bool interfaceInitialized = false; List genericInstances; bool isDelegate; ILRuntimeType reflectionType; IType firstCLRBaseType, firstCLRInterface; int hashCode = -1; static int instance_id = 0x10000000; public TypeDefinition TypeDefinition { get { return definition; } } public TypeReference TypeReference { get { return typeRef; } set { typeRef = value; RetriveDefinitino(value); } } public IType BaseType { get { if (!baseTypeInitialized) InitializeBaseType(); return baseType; } } public IType[] Implements { get { if (!interfaceInitialized) InitializeInterfaces(); return interfaces; } } public ILTypeStaticInstance StaticInstance { get { if (fieldMapping == null) InitializeFields(); if (methods == null) InitializeMethods(); return staticInstance; } } public IType[] FieldTypes { get { if (fieldMapping == null) InitializeFields(); return fieldTypes; } } public IType[] StaticFieldTypes { get { if (fieldMapping == null) InitializeFields(); return staticFieldTypes; } } public FieldDefinition[] StaticFieldDefinitions { get { if (fieldMapping == null) InitializeFields(); return staticFieldDefinitions; } } public Dictionary FieldMapping { get { if (fieldMapping == null) InitializeFields(); return fieldMapping; } } public IType FirstCLRBaseType { get { if (!baseTypeInitialized) InitializeBaseType(); return firstCLRBaseType; } } public IType FirstCLRInterface { get { if (!interfaceInitialized) InitializeInterfaces(); return firstCLRInterface; } } public bool HasGenericParameter { get { return definition.HasGenericParameters && genericArguments == null; } } public Dictionary StaticFieldMapping { get { return staticFieldMapping; } } public ILRuntime.Runtime.Enviorment.AppDomain AppDomain { get { return appdomain; } } internal int FieldStartIndex { get { if (fieldStartIdx < 0) { if (BaseType != null) { if (BaseType is ILType) { fieldStartIdx = ((ILType)BaseType).TotalFieldCount; } else fieldStartIdx = 0; } else fieldStartIdx = 0; } return fieldStartIdx; } } public int TotalFieldCount { get { if (totalFieldCnt < 0) { if (fieldMapping == null) InitializeFields(); if (BaseType != null) { if (BaseType is ILType) { totalFieldCnt = ((ILType)BaseType).TotalFieldCount + fieldTypes.Length; } else totalFieldCnt = fieldTypes.Length; } else totalFieldCnt = fieldTypes.Length; } return totalFieldCnt; } } /// /// 初始化IL类型 /// /// MONO返回的类型定义 /// ILdomain public ILType(TypeReference def, Runtime.Enviorment.AppDomain domain) { this.typeRef = def; RetriveDefinitino(def); appdomain = domain; } /// /// 加载类型 /// /// void RetriveDefinitino(TypeReference def) { if (!def.IsGenericParameter) { if (def is TypeSpecification) RetriveDefinitino(def.GetElementType()); else definition = def as TypeDefinition; } } public bool IsGenericInstance { get { return genericArguments != null; } } public KeyValuePair[] GenericArguments { get { return genericArguments; } } public IType ElementType { get { return elementType; } } public bool IsArray { get; private set; } private bool? isValueType; public bool IsValueType { get { if (isValueType == null) isValueType = definition.IsValueType; return isValueType.Value; } } public bool IsDelegate { get { if (!baseTypeInitialized) InitializeBaseType(); return isDelegate; } } public bool IsPrimitive { get { return false; } } public Type TypeForCLR { get { if (!baseTypeInitialized) InitializeBaseType(); if (typeRef is ArrayType) { return arrayCLRType; } else if (typeRef is ByReferenceType) { return byRefCLRType; } else if (definition.IsEnum) { if (enumType == null) InitializeFields(); return enumType.TypeForCLR; } else if (FirstCLRBaseType != null && FirstCLRBaseType is CrossBindingAdaptor) { return ((CrossBindingAdaptor)FirstCLRBaseType).RuntimeType.TypeForCLR; } else if (FirstCLRInterface != null && FirstCLRInterface is CrossBindingAdaptor) { return ((CrossBindingAdaptor)FirstCLRInterface).RuntimeType.TypeForCLR; } else return typeof(ILTypeInstance); } } public Type ReflectionType { get { if (reflectionType == null) reflectionType = new ILRuntimeType(this); return reflectionType; } } public IType ByRefType { get { return byRefType; } } public IType ArrayType { get { return arrayType; } } public bool IsEnum { get { return definition.IsEnum; } } public string FullName { get { return typeRef.FullName; } } public string Name { get { return typeRef.Name; } } public List GetMethods() { if (methods == null) InitializeMethods(); List res = new List(); foreach (var i in methods) { foreach (var j in i.Value) res.Add(j); } return res; } void InitializeInterfaces() { interfaceInitialized = true; if (definition.HasInterfaces) { interfaces = new IType[definition.Interfaces.Count]; for (int i = 0; i < interfaces.Length; i++) { interfaces[i] = appdomain.GetType(definition.Interfaces[i], this, null); //only one clrInterface is valid if (interfaces[i] is CLRType && firstCLRInterface == null) { CrossBindingAdaptor adaptor; if (appdomain.CrossBindingAdaptors.TryGetValue(interfaces[i].TypeForCLR, out adaptor)) { interfaces[i] = adaptor; firstCLRInterface = adaptor; } else throw new TypeLoadException("Cannot find Adaptor for:" + interfaces[i].TypeForCLR.ToString()); } } } } void InitializeBaseType() { if (definition.BaseType != null) { bool specialProcess = false; List spIdx = null; if (definition.BaseType.IsGenericInstance) { GenericInstanceType git = definition.BaseType as GenericInstanceType; var elementType = appdomain.GetType(definition.BaseType.GetElementType(), this, null); if (elementType is CLRType) { for (int i = 0; i < git.GenericArguments.Count; i++) { var ga = git.GenericArguments[i]; if (ga == typeRef) { specialProcess = true; if (spIdx == null) spIdx = new List(); spIdx.Add(i); } } } } if (specialProcess) { //如果泛型参数是自身,则必须要特殊处理,否则会StackOverflow var elementType = appdomain.GetType(definition.BaseType.GetElementType(), this, null); foreach (var i in appdomain.CrossBindingAdaptors) { if (i.Key.IsGenericType && !i.Key.IsGenericTypeDefinition) { var gd = i.Key.GetGenericTypeDefinition(); if (gd == elementType.TypeForCLR) { var ga = i.Key.GetGenericArguments(); bool match = true; foreach (var j in spIdx) { if (ga[j] != i.Value.AdaptorType) { match = false; break; } } if (match) { baseType = i.Value; break; } } } } if (baseType == null) { throw new TypeLoadException("Cannot find Adaptor for:" + definition.BaseType.FullName); } } else { baseType = appdomain.GetType(definition.BaseType, this, null); if (baseType is CLRType) { if (baseType.TypeForCLR == typeof(Enum) || baseType.TypeForCLR == typeof(object) || baseType.TypeForCLR == typeof(ValueType) || baseType.TypeForCLR == typeof(System.Enum)) {//都是这样,无所谓 baseType = null; } else if (baseType.TypeForCLR == typeof(MulticastDelegate)) { baseType = null; isDelegate = true; } else { CrossBindingAdaptor adaptor; if (appdomain.CrossBindingAdaptors.TryGetValue(baseType.TypeForCLR, out adaptor)) { baseType = adaptor; } else throw new TypeLoadException("Cannot find Adaptor for:" + baseType.TypeForCLR.ToString()); //继承了其他系统类型 //env.logger.Log_Error("ScriptType:" + Name + " Based On a SystemType:" + BaseType.Name); //HasSysBase = true; //throw new Exception("不得继承系统类型,脚本类型系统和脚本类型系统是隔离的"); } } } } var curBase = baseType; while (curBase is ILType) { curBase = curBase.BaseType; } firstCLRBaseType = curBase; baseTypeInitialized = true; } public IMethod GetMethod(string name) { if (methods == null) InitializeMethods(); List lst; if (methods.TryGetValue(name, out lst)) { return lst[0]; } return null; } public IMethod GetMethod(string name, int paramCount, bool declaredOnly = false) { if (methods == null) InitializeMethods(); List lst; if (methods.TryGetValue(name, out lst)) { foreach (var i in lst) { if (i.ParameterCount == paramCount) return i; } } if (declaredOnly) return null; else { //skip clr base type, this doesn't make any sense if (BaseType != null && !(BaseType is CrossBindingAdaptor)) return BaseType.GetMethod(name, paramCount, false); else return null; } } void InitializeMethods() { methods = new Dictionary>(); constructors = new List(); foreach (var i in definition.Methods) { if (i.IsConstructor) { if (i.IsStatic) staticConstructor = new ILMethod(i, this, appdomain); else constructors.Add(new ILMethod(i, this, appdomain)); } else { List lst; if (!methods.TryGetValue(i.Name, out lst)) { lst = new List(); methods[i.Name] = lst; } var m = new ILMethod(i, this, appdomain); lst.Add(new ILMethod(i, this, appdomain)); } } if (staticConstructor != null && (!TypeReference.HasGenericParameters || IsGenericInstance)) { appdomain.Invoke(staticConstructor, null, null); } } public IMethod GetVirtualMethod(IMethod method) { IType[] genericArguments = null; if (method.IsGenericInstance) { if (method is ILMethod) { genericArguments = ((ILMethod)method).GenericArugmentsArray; } else { genericArguments = ((CLRMethod)method).GenericArguments; } } var m = GetMethod(method.Name, method.Parameters, genericArguments, method.ReturnType, true); if (m == null) { if (BaseType != null) { return BaseType.GetVirtualMethod(method); } else return null;//BaseType == null means base type is Object or Enum } else if (m.IsGenericInstance == method.IsGenericInstance) return m; else return method; } public IMethod GetMethod(string name, List param, IType[] genericArguments, IType returnType = null, bool declaredOnly = false) { if (methods == null) InitializeMethods(); List lst; IMethod genericMethod = null; if (methods.TryGetValue(name, out lst)) { for (var idx = 0; idx < lst.Count; idx++) { var i = lst[idx]; int pCnt = param != null ? param.Count : 0; if (i.ParameterCount == pCnt) { bool match = true; if (genericArguments != null && i.GenericParameterCount == genericArguments.Length) { genericMethod = CheckGenericParams(i, param, ref match); } else { match = CheckGenericArguments(i, genericArguments); if (!match) continue; for (int j = 0; j < pCnt; j++) { if (param[j] != i.Parameters[j]) { match = false; break; } } if (match) { match = returnType == null || i.ReturnType == returnType; } if (match) return i; } } } } if (genericArguments != null && genericMethod != null) { var m = genericMethod.MakeGenericMethod(genericArguments); lst.Add((ILMethod)m); return m; } if (declaredOnly) return null; else { if (BaseType != null) return BaseType.GetMethod(name, param, genericArguments, returnType, false); else return null; } } bool CheckGenericArguments(ILMethod i, IType[] genericArguments) { if (genericArguments == null) { return i.GenericArguments == null; } else { if (i.GenericArguments == null) return false; else if (i.GenericArguments.Length != genericArguments.Length) return false; if (i.GenericArguments.Length == genericArguments.Length) { for (int j = 0; j < genericArguments.Length; j++) { if (i.GenericArguments[j].Value != genericArguments[j]) return false; } return true; } else return false; } } ILMethod CheckGenericParams(ILMethod i, List param, ref bool match) { ILMethod genericMethod = null; if (param != null) { for (int j = 0; j < param.Count; j++) { var p = i.Parameters[j]; if (p.HasGenericParameter) { //TODO should match the generic parameters; continue; } if (param[j] != p) { match = false; break; } } } if (match) { genericMethod = i; } return genericMethod; } public List GetConstructors() { if (constructors == null) InitializeMethods(); return constructors; } public IMethod GetStaticConstroctor() { if (constructors == null) InitializeMethods(); return staticConstructor; } public IMethod GetConstructor(int paramCnt) { if (constructors == null) InitializeMethods(); foreach (var i in constructors) { if (i.ParameterCount == paramCnt) { return i; } } return null; } public IMethod GetConstructor(List param) { if (constructors == null) InitializeMethods(); foreach (var i in constructors) { if (i.ParameterCount == param.Count) { bool match = true; for (int j = 0; j < param.Count; j++) { if (param[j] != i.Parameters[j]) { match = false; break; } } if (match) return i; } } return null; } public int GetFieldIndex(object token) { if (fieldMapping == null) InitializeFields(); int idx; int hashCode = token.GetHashCode(); if (fieldTokenMapping.TryGetValue(hashCode, out idx)) return idx; FieldReference f = token as FieldReference; if (staticFieldMapping != null && staticFieldMapping.TryGetValue(f.Name, out idx)) { fieldTokenMapping[hashCode] = idx; return idx; } if (fieldMapping.TryGetValue(f.Name, out idx)) { fieldTokenMapping[hashCode] = idx; return idx; } return -1; } public IType GetField(string name, out int fieldIdx) { if (fieldMapping == null) InitializeFields(); if (fieldMapping.TryGetValue(name, out fieldIdx)) { return fieldTypes[fieldIdx - FieldStartIndex]; } else if (BaseType != null && BaseType is ILType) { return ((ILType)BaseType).GetField(name, out fieldIdx); } else return null; } public IType GetField(int fieldIdx, out FieldDefinition fd) { if (fieldMapping == null) InitializeFields(); if (fieldIdx < FieldStartIndex) return ((ILType)BaseType).GetField(fieldIdx, out fd); else { fd = fieldDefinitions[fieldIdx - FieldStartIndex]; return fieldTypes[fieldIdx - FieldStartIndex]; } } void InitializeFields() { fieldMapping = new Dictionary(); fieldTypes = new IType[definition.Fields.Count]; fieldDefinitions = new FieldDefinition[definition.Fields.Count]; var fields = definition.Fields; int idx = FieldStartIndex; int idxStatic = 0; for (int i = 0; i < fields.Count; i++) { var field = fields[i]; if (field.IsStatic) { //It makes no sence to initialize if (!TypeReference.HasGenericParameters || IsGenericInstance) { if (staticFieldTypes == null) { staticFieldTypes = new IType[definition.Fields.Count]; staticFieldDefinitions = new FieldDefinition[definition.Fields.Count]; staticFieldMapping = new Dictionary(); } staticFieldMapping[field.Name] = idxStatic; staticFieldDefinitions[idxStatic] = field; if (field.FieldType.IsGenericParameter) { staticFieldTypes[idxStatic] = FindGenericArgument(field.FieldType.Name); } else staticFieldTypes[idxStatic] = appdomain.GetType(field.FieldType, this, null); idxStatic++; } } else { fieldMapping[field.Name] = idx; fieldDefinitions[idx - FieldStartIndex] = field; if (field.FieldType.IsGenericParameter) { fieldTypes[idx - FieldStartIndex] = FindGenericArgument(field.FieldType.Name); } else fieldTypes[idx - FieldStartIndex] = appdomain.GetType(field.FieldType, this, null); if (IsEnum) { enumType = fieldTypes[idx - FieldStartIndex]; } idx++; } } Array.Resize(ref fieldTypes, idx - FieldStartIndex); Array.Resize(ref fieldDefinitions, idx - FieldStartIndex); if (staticFieldTypes != null) { Array.Resize(ref staticFieldTypes, idxStatic); Array.Resize(ref staticFieldDefinitions, idxStatic); staticInstance = new ILTypeStaticInstance(this); } } public IType FindGenericArgument(string key) { if (genericArguments != null) { foreach (var i in genericArguments) { if (i.Key == key) return i.Value; } } return null; } public bool CanAssignTo(IType type) { bool res = false; if (this == type) { return true; } if (BaseType != null) { res = BaseType.CanAssignTo(type); if (res) return true; } if (Implements != null) { for (int i = 0; i < interfaces.Length; i++) { var im = interfaces[i]; res = im.CanAssignTo(type); if (res) return true; } } return res; } public ILTypeInstance Instantiate(bool callDefaultConstructor = true) { var res = new ILTypeInstance(this); if (callDefaultConstructor) { var m = GetConstructor(CLR.Utils.Extensions.EmptyParamList); if (m != null) { appdomain.Invoke(m, res, null); } } return res; } public IType MakeGenericInstance(KeyValuePair[] genericArguments) { if (genericInstances == null) genericInstances = new List(); foreach (var i in genericInstances) { bool match = true; for (int j = 0; j < genericArguments.Length; j++) { if (i.genericArguments[j].Value != genericArguments[j].Value) { match = false; break; } } if (match) return i; } var res = new ILType(definition, appdomain); res.genericArguments = genericArguments; genericInstances.Add(res); return res; } public IType MakeByRefType() { if (byRefType == null) { var def = new ByReferenceType(typeRef); byRefType = new ILType(def, appdomain); ((ILType)byRefType).elementType = this; ((ILType)byRefType).byRefCLRType = this.TypeForCLR.MakeByRefType(); } return byRefType; } public IType MakeArrayType() { if (arrayType == null) { var def = new ArrayType(typeRef); arrayType = new ILType(def, appdomain); ((ILType)arrayType).IsArray = true; ((ILType)arrayType).elementType = this; ((ILType)arrayType).arrayCLRType = this.TypeForCLR.MakeArrayType(); } return arrayType; } public IType ResolveGenericType(IType contextType) { var ga = contextType.GenericArguments; IType[] kv = new IType[definition.GenericParameters.Count]; for (int i = 0; i < kv.Length; i++) { var gp = definition.GenericParameters[i]; string name = gp.Name; foreach (var j in ga) { if (j.Key == name) { kv[i] = j.Value; break; } } } foreach (var i in genericInstances) { bool match = true; for (int j = 0; j < kv.Length; j++) { if (i.genericArguments[j].Value != kv[j]) { match = false; break; } } if (match) return i; } return null; } public override int GetHashCode() { if (hashCode == -1) hashCode = System.Threading.Interlocked.Add(ref instance_id, 1); return hashCode; } public override string ToString() { return FullName; } } } ================================================ FILE: ILRuntime/ILRuntime/CLR/TypeSystem/IType.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.Method; namespace ILRuntime.CLR.TypeSystem { public interface IType { bool IsGenericInstance { get; } KeyValuePair[] GenericArguments { get; } Type TypeForCLR { get; } Type ReflectionType { get; } IType BaseType { get; } IType[] Implements { get; } IType ByRefType { get; } IType ArrayType { get; } string FullName { get; } string Name { get; } bool IsArray { get; } bool IsValueType { get; } bool IsDelegate { get; } bool IsPrimitive { get; } bool HasGenericParameter { get; } ILRuntime.Runtime.Enviorment.AppDomain AppDomain { get; } /// /// Get a specified Method in this type /// /// Name of the Type /// Parameter count /// True to search the methods decleared in this type only, false to search base types. /// IMethod GetMethod(string name, int paramCount, bool declaredOnly = false); /// /// Get a specified Method in this type /// /// Name of the Type /// List of parameter's types /// List of Generic Arguments /// Return Type /// True to search the methods decleared in this type only, false to search base types. /// IMethod GetMethod(string name, List param, IType[] genericArguments, IType returnType = null, bool declaredOnly = false); IMethod GetVirtualMethod(IMethod method); List GetMethods(); int GetFieldIndex(object token); IMethod GetConstructor(List param); bool CanAssignTo(IType type); IType MakeGenericInstance(KeyValuePair[] genericArguments); IType MakeByRefType(); IType MakeArrayType(); IType FindGenericArgument(string key); IType ResolveGenericType(IType contextType); } } ================================================ FILE: ILRuntime/ILRuntime/CLR/Utils/Extensions.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.Other; using Mono.Cecil; using ILRuntime.Runtime.Intepreter; namespace ILRuntime.CLR.Utils { public delegate TResult Func(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); public static class Extensions { public static List EmptyParamList = new List(); public static List GetParamList(this MethodReference def, ILRuntime.Runtime.Enviorment.AppDomain appdomain, IType contextType, IMethod contextMethod, IType[] genericArguments) { if (def.HasParameters) { List param = new List(); var dt = appdomain.GetType(def.DeclaringType, contextType, contextMethod); foreach (var i in def.Parameters) { IType t = null; t = appdomain.GetType(i.ParameterType, dt, null); if (t == null && def.IsGenericInstance) { GenericInstanceMethod gim = (GenericInstanceMethod)def; string name = i.ParameterType.IsByReference ? i.ParameterType.GetElementType().FullName : i.ParameterType.FullName; for (int j = 0; j < gim.GenericArguments.Count; j++) { var gp = gim.ElementMethod.GenericParameters[j]; var ga = gim.GenericArguments[j]; if (name == gp.Name) { t = appdomain.GetType(ga, contextType, contextMethod); if (t == null && genericArguments != null) t = genericArguments[j]; break; } else if (name.Contains(gp.Name)) { if (name == gp.Name) { name = ga.FullName; } else if (name == gp.Name + "[]") { name = ga.FullName + "[]"; } else { /*name = name.Replace("<" + gp.Name + ">", "<" + ga.FullName + ">"); name = name.Replace("<" + gp.Name + "[", "<" + ga.FullName + "["); name = name.Replace("<" + gp.Name + ",", "<" + ga.FullName + ","); name = name.Replace("," + gp.Name + ">", "," + ga.FullName + ">"); name = name.Replace("," + gp.Name + "[", "," + ga.FullName + "["); name = name.Replace("," + gp.Name + ",", "," + ga.FullName + ","); name = name.Replace("," + gp.Name + "[", "," + ga.FullName + "[");*/ name = ReplaceGenericArgument(name, gp.Name, ga.FullName); } } } if (t == null) t = appdomain.GetType(name); } param.Add(t); } return param; } else return EmptyParamList; } static string ReplaceGenericArgument(string typename, string argumentName, string argumentType) { string baseType; StringBuilder sb = new StringBuilder(); List ga; bool isArray; Runtime.Enviorment.AppDomain.ParseGenericType(typename, out baseType, out ga, out isArray); if (baseType == argumentName) sb.Append(argumentType); else sb.Append(baseType); if (ga != null && ga.Count > 0) { sb.Append("<"); bool isFirst = true; foreach(var i in ga) { if (isFirst) isFirst = false; else sb.Append(","); sb.Append(ReplaceGenericArgument(i, argumentName, argumentType)); } sb.Append(">"); } if (isArray) sb.Append("[]"); return sb.ToString(); } [Flags] public enum TypeFlags { Default = 0, IsPrimitive = 0x1, IsByRef = 0x2, IsEnum = 0x4, IsDelegate = 0x8, IsValueType = 0x10, } private static readonly Dictionary typeFlags = new Dictionary(new ByReferenceKeyComparer()); public static bool FastIsEnum(this Type pt) { return (pt.GetTypeFlags() & TypeFlags.IsEnum) != 0; } public static bool FastIsByRef(this Type pt) { return (pt.GetTypeFlags() & TypeFlags.IsByRef) != 0; } public static bool FastIsPrimitive(this Type pt) { return (pt.GetTypeFlags() & TypeFlags.IsPrimitive) != 0; } public static bool FastIsValueType(this Type pt) { return (pt.GetTypeFlags() & TypeFlags.IsValueType) != 0; } public static TypeFlags GetTypeFlags(this Type pt) { var result = TypeFlags.Default; if (!typeFlags.TryGetValue(pt, out result)) { if (pt.IsPrimitive) { result |= TypeFlags.IsPrimitive; } if (pt == typeof(Delegate) || pt.IsSubclassOf(typeof(Delegate))) { result |= TypeFlags.IsDelegate; } if (pt.IsByRef) { result |= TypeFlags.IsByRef; } if (pt.IsEnum) { result |= TypeFlags.IsEnum; } if (pt.IsValueType) { result |= TypeFlags.IsValueType; } typeFlags[pt] = result; } return result; } public static object CheckCLRTypes(this Type pt, object obj) { if (obj == null) return null; var typeFlags = GetTypeFlags(pt); if ((typeFlags & TypeFlags.IsPrimitive) != 0 && pt != typeof(int)) { if (pt == typeof(bool) && !(obj is bool)) { obj = (int)obj == 1; } else if (pt == typeof(byte) && !(obj is byte)) obj = (byte)(int)obj; else if (pt == typeof(short) && !(obj is short)) obj = (short)(int)obj; else if (pt == typeof(char) && !(obj is char)) obj = (char)(int)obj; else if (pt == typeof(ushort) && !(obj is ushort)) obj = (ushort)(int)obj; else if (pt == typeof(uint) && !(obj is uint)) obj = (uint)(int)obj; else if (pt == typeof(sbyte) && !(obj is sbyte)) obj = (sbyte)(int)obj; else if (pt == typeof(ulong) && !(obj is ulong)) { obj = (ulong)(long)obj; } } else if (obj is ILRuntime.Reflection.ILRuntimeWrapperType) { obj = ((ILRuntime.Reflection.ILRuntimeWrapperType)obj).RealType; } else if ((typeFlags & TypeFlags.IsDelegate) != 0) { if (obj is Delegate) return obj; if (pt == typeof(Delegate)) return ((IDelegateAdapter)obj).Delegate; return ((IDelegateAdapter)obj).GetConvertor(pt); } else if ((typeFlags & TypeFlags.IsByRef) != 0) { return CheckCLRTypes(pt.GetElementType(), obj); } else if ((typeFlags & TypeFlags.IsEnum) != 0) { return Enum.ToObject(pt, obj); } else if (obj is ILTypeInstance) { var adapter = obj as IDelegateAdapter; if (adapter != null && pt != typeof(ILTypeInstance)) { return adapter.Delegate; } if (!(obj is ILEnumTypeInstance)) { var ins = (ILTypeInstance)obj; if (ins.IsValueType) ins = ins.Clone(); return ins.CLRInstance; } } return obj; } } } ================================================ FILE: ILRuntime/ILRuntime/Other/ByReferenceKeyComparer.cs ================================================ using System.Collections.Generic; using System.Runtime.CompilerServices; namespace ILRuntime.Other { class ByReferenceKeyComparer : IEqualityComparer { public bool Equals(T x, T y) { return object.ReferenceEquals(x, y); } public int GetHashCode(T obj) { return RuntimeHelpers.GetHashCode(obj); } } } ================================================ FILE: ILRuntime/ILRuntime/Other/DelegateExportAttribute.cs ================================================ namespace ILRuntime.Other { /// /// A Delegate Custom Attr, It tells the CodeGenerationTools : this delegate need to register a delegate convertor,when generate ILRuntimeHelper.cs file. /// public class DelegateExportAttribute : System.Attribute { } } ================================================ FILE: ILRuntime/ILRuntime/Other/NeedAdaptorAttribute.cs ================================================ namespace ILRuntime.Other { /// /// A Class Custom Attr, It tells the CodeGenerationTools :there is a class need to generate an adaptor for ILScript /// public class NeedAdaptorAttribute : System.Attribute { } } ================================================ FILE: ILRuntime/ILRuntime/Other/ThreadSafeDictionary.cs ================================================ using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Runtime.Versioning; using System.Threading; namespace ILRuntime.Other { /// /// A thread safe dictionary for internal use /// /// /// class ThreadSafeDictionary : IDictionary { Dictionary dic = new Dictionary(); public Dictionary InnerDictionary { get { return dic; } } public V this[K key] { get { lock(dic) return dic[key]; } set { lock(dic) dic[key] = value; } } public int Count { get { lock(dic) return dic.Count; } } public bool IsReadOnly { get { lock(dic) return IsReadOnly; } } public ICollection Keys { get { throw new NotImplementedException(); } } public ICollection Values { get { throw new NotImplementedException(); } } public void Add(KeyValuePair item) { lock (dic) dic.Add(item.Key, item.Value); } public void Add(K key, V value) { lock(dic) dic.Add(key, value); } public void Clear() { lock(dic) dic.Clear(); } public bool Contains(KeyValuePair item) { lock(dic) return dic.ContainsKey(item.Key); } public bool ContainsKey(K key) { lock(dic) return dic.ContainsKey(key); } public void CopyTo(KeyValuePair[] array, int arrayIndex) { throw new NotImplementedException(); } public IEnumerator> GetEnumerator() { throw new NotImplementedException(); } public bool Remove(KeyValuePair item) { throw new NotImplementedException(); } public bool Remove(K key) { lock(dic) return dic.Remove(key); } public bool TryGetValue(K key, out V value) { lock(dic) return dic.TryGetValue(key, out value); } IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); } } } ================================================ FILE: ILRuntime/ILRuntime/Other/UncheckedList.cs ================================================ using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Runtime.Versioning; using System.Threading; namespace ILRuntime.Other { /// /// This is a copy of the latest .NET framework 4.5 List implementation, with all extraneous checking removed. /// /// [Serializable] public class UncheckedList : IList, ICollection, IEnumerable, IEnumerable, IList, ICollection { private const int _defaultCapacity = 4; private T[] _items; private int _size; private int _version; [NonSerialized] private Object _syncRoot; private static readonly T[] _emptyArray = new T[0]; // Constructs a UncheckedList. The list is initially empty and has a capacity // of zero. Upon adding the first element to the list the capacity is // increased to _defaultCapacity, and then increased in multiples of two // as required. public UncheckedList() { _items = _emptyArray; } // Constructs a UncheckedList with a given initial capacity. The list is // initially empty, but will have room for the given number of elements // before any reallocations are required. // public UncheckedList(int capacity) { if (capacity == 0) _items = _emptyArray; else _items = new T[capacity]; } // Constructs a UncheckedList, copying the contents of the given collection. The // size and capacity of the new list will both be equal to the size of the // given collection. // public UncheckedList(IEnumerable collection) { ICollection c = collection as ICollection; if (c != null) { int count = c.Count; if (count == 0) { _items = _emptyArray; } else { _items = new T[count]; c.CopyTo(_items, 0); _size = count; } } else { _size = 0; _items = _emptyArray; AddEnumerable(collection); } } // Gets and sets the capacity of this list. The capacity is the size of // the internal array used to hold items. When set, the internal // array of the list is reallocated to the given capacity. // public int Capacity { get { return _items.Length; } set { if (value != _items.Length) { if (value > 0) { T[] newItems = new T[value]; if (_size > 0) { Array.Copy(_items, 0, newItems, 0, _size); } _items = newItems; } else { _items = _emptyArray; } } } } // Read-only property describing how many elements are in the UncheckedList. public int Count { get { return _size; } } bool System.Collections.IList.IsFixedSize { get { return false; } } // Is this UncheckedList read-only? bool ICollection.IsReadOnly { get { return false; } } bool System.Collections.IList.IsReadOnly { get { return false; } } // Is this UncheckedList synchronized (thread-safe)? bool System.Collections.ICollection.IsSynchronized { get { return false; } } // Synchronization root for this object. Object System.Collections.ICollection.SyncRoot { get { if (_syncRoot == null) { System.Threading.Interlocked.CompareExchange(ref _syncRoot, new Object(), null); } return _syncRoot; } } // Sets or Gets the element at the given index. // public T this[int index] { get { return _items[index]; } set { _items[index] = value; _version++; } } private static bool IsCompatibleObject(object value) { // Non-null values are fine. Only accept nulls if T is a class or Nullable. // Note that default(T) is not equal to null for value types except when T is Nullable. return ((value is T) || (value == null && default(T) == null)); } Object System.Collections.IList.this[int index] { get { return this[index]; } set { try { this[index] = (T)value; } catch (InvalidCastException) { } } } // Adds the given object to the end of this list. The size of the list is // increased by one. If required, the capacity of the list is doubled // before adding the new element. public void Add(T item) { var array = _items; var size = _size; _version++; if ((uint)size < (uint)array.Length) { _size = size + 1; array[size] = item; } else { AddWithResize(item); } } // Non-inline from UncheckedList.Add to improve its code quality as uncommon path private void AddWithResize(T item) { var size = _size; EnsureCapacity(size + 1); _size = size + 1; _items[size] = item; } int System.Collections.IList.Add(Object item) { try { Add((T)item); } catch (InvalidCastException) { } return Count - 1; } // Adds the elements of the given collection to the end of this list. If // required, the capacity of the list is increased to twice the previous // capacity or the new size, whichever is larger. // public void AddRange(IEnumerable collection) { InsertRange(_size, collection); } public ReadOnlyCollection AsReadOnly() { return new ReadOnlyCollection(this); } // Searches a section of the list for a given element using a binary search // algorithm. Elements of the list are compared to the search value using // the given IComparer interface. If comparer is null, elements of // the list are compared to the search value using the IComparable // interface, which in that case must be implemented by all elements of the // list and the given search value. This method assumes that the given // section of the list is already sorted; if this is not the case, the // result will be incorrect. // // The method returns the index of the given value in the list. If the // list does not contain the given value, the method returns a negative // integer. The bitwise complement operator (~) can be applied to a // negative result to produce the index of the first element (if any) that // is larger than the given search value. This is also the index at which // the search value should be inserted into the list in order for the list // to remain sorted. // // The method uses the Array.BinarySearch method to perform the // search. // public int BinarySearch(int index, int count, T item, IComparer comparer) { if (index < 0) return -1; return Array.BinarySearch(_items, index, count, item, comparer); } public int BinarySearch(T item) { return BinarySearch(0, Count, item, null); } public int BinarySearch(T item, IComparer comparer) { return BinarySearch(0, Count, item, comparer); } // Clears the contents of UncheckedList. public void Clear() { if (!typeof(T).IsValueType) { int size = _size; _size = 0; _version++; if (size > 0) { Array.Clear(_items, 0, size); // Clear the elements so that the gc can reclaim the references. } } else { _size = 0; _version++; } } // Contains returns true if the specified element is in the UncheckedList. // It does a linear, O(n) search. Equality is determined by calling // EqualityComparer.Default.Equals(). public bool Contains(T item) { // PERF: IndexOf calls Array.IndexOf, which internally // calls EqualityComparer.Default.IndexOf, which // is specialized for different types. This // boosts performance since instead of making a // virtual method call each iteration of the loop, // via EqualityComparer.Default.Equals, we // only make one virtual call to EqualityComparer.IndexOf. return _size != 0 && IndexOf(item) != -1; } bool System.Collections.IList.Contains(Object item) { if (IsCompatibleObject(item)) { return Contains((T)item); } return false; } public UncheckedList ConvertAll(Converter converter) { UncheckedList list = new UncheckedList(_size); for (int i = 0; i < _size; i++) { list._items[i] = converter(_items[i]); } list._size = _size; return list; } // Copies this UncheckedList into array, which must be of a // compatible array type. // public void CopyTo(T[] array) { CopyTo(array, 0); } // Copies this UncheckedList into array, which must be of a // compatible array type. // void System.Collections.ICollection.CopyTo(Array array, int arrayIndex) { try { // Array.Copy will check for NULL. Array.Copy(_items, 0, array, arrayIndex, _size); } catch (ArrayTypeMismatchException) { } } // Copies a section of this list to the given array at the given index. // // The method uses the Array.Copy method to copy the elements. // public void CopyTo(int index, T[] array, int arrayIndex, int count) { // Delegate rest of error checking to Array.Copy. Array.Copy(_items, index, array, arrayIndex, count); } public void CopyTo(T[] array, int arrayIndex) { // Delegate rest of error checking to Array.Copy. Array.Copy(_items, 0, array, arrayIndex, _size); } // Ensures that the capacity of this list is at least the given minimum // value. If the current capacity of the list is less than min, the // capacity is increased to twice the current capacity or to min, // whichever is larger. private void EnsureCapacity(int min) { if (_items.Length < min) { int newCapacity = _items.Length == 0 ? _defaultCapacity : _items.Length * 2; // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow. // Note that this check works even when _items.Length overflowed thanks to the (uint) cast if ((uint) newCapacity > Int32.MaxValue) newCapacity = Int32.MaxValue; if (newCapacity < min) newCapacity = min; Capacity = newCapacity; } } public bool Exists(Predicate match) { return FindIndex(match) != -1; } public T Find(Predicate match) { for (int i = 0; i < _size; i++) { if (match(_items[i])) { return _items[i]; } } return default(T); } public UncheckedList FindAll(Predicate match) { UncheckedList list = new UncheckedList(); for (int i = 0; i < _size; i++) { if (match(_items[i])) { list.Add(_items[i]); } } return list; } public int FindIndex(Predicate match) { return FindIndex(0, _size, match); } public int FindIndex(int startIndex, Predicate match) { return FindIndex(startIndex, _size - startIndex, match); } public int FindIndex(int startIndex, int count, Predicate match) { int endIndex = startIndex + count; for (int i = startIndex; i < endIndex; i++) { if (match(_items[i])) return i; } return -1; } public T FindLast(Predicate match) { for (int i = _size - 1; i >= 0; i--) { if (match(_items[i])) { return _items[i]; } } return default(T); } public int FindLastIndex(Predicate match) { return FindLastIndex(_size - 1, _size, match); } public int FindLastIndex(int startIndex, Predicate match) { return FindLastIndex(startIndex, startIndex + 1, match); } public int FindLastIndex(int startIndex, int count, Predicate match) { int endIndex = startIndex - count; for (int i = startIndex; i > endIndex; i--) { if (match(_items[i])) { return i; } } return -1; } public void ForEach(Action action) { int version = _version; for (int i = 0; i < _size; i++) { if (version != _version) { break; } action(_items[i]); } } // Returns an enumerator for this list with the given // permission for removal of elements. If modifications made to the list // while an enumeration is in progress, the MoveNext and // GetObject methods of the enumerator will throw an exception. // public Enumerator GetEnumerator() { return new Enumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(this); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return new Enumerator(this); } public UncheckedList GetRange(int index, int count) { UncheckedList list = new UncheckedList(count); Array.Copy(_items, index, list._items, 0, count); list._size = count; return list; } // Returns the index of the first occurrence of a given value in a range of // this list. The list is searched forwards from beginning to end. // The elements of the list are compared to the given value using the // Object.Equals method. // // This method uses the Array.IndexOf method to perform the // search. // public int IndexOf(T item) { return Array.IndexOf(_items, item, 0, _size); } int System.Collections.IList.IndexOf(Object item) { if (IsCompatibleObject(item)) { return IndexOf((T)item); } return -1; } // Returns the index of the first occurrence of a given value in a range of // this list. The list is searched forwards, starting at index // index and ending at count number of elements. The // elements of the list are compared to the given value using the // Object.Equals method. // // This method uses the Array.IndexOf method to perform the // search. // public int IndexOf(T item, int index) { return Array.IndexOf(_items, item, index, _size - index); } // Returns the index of the first occurrence of a given value in a range of // this list. The list is searched forwards, starting at index // index and upto count number of elements. The // elements of the list are compared to the given value using the // Object.Equals method. // // This method uses the Array.IndexOf method to perform the // search. // public int IndexOf(T item, int index, int count) { return Array.IndexOf(_items, item, index, count); } // Inserts an element into this list at a given index. The size of the list // is increased by one. If required, the capacity of the list is doubled // before inserting the new element. // public void Insert(int index, T item) { if (_size == _items.Length) EnsureCapacity(_size + 1); if (index < _size) { Array.Copy(_items, index, _items, index + 1, _size - index); } _items[index] = item; _size++; _version++; } void System.Collections.IList.Insert(int index, Object item) { try { Insert(index, (T)item); } catch (InvalidCastException) { } } // Inserts the elements of the given collection at a given index. If // required, the capacity of the list is increased to twice the previous // capacity or the new size, whichever is larger. Ranges may be added // to the end of the list by setting index to the UncheckedList's size. // public void InsertRange(int index, IEnumerable collection) { ICollection c = collection as ICollection; if (c != null) { // if collection is ICollection int count = c.Count; if (count > 0) { EnsureCapacity(_size + count); if (index < _size) { Array.Copy(_items, index, _items, index + count, _size - index); } // If we're inserting a UncheckedList into itself, we want to be able to deal with that. if (this == c) { // Copy first part of _items to insert location Array.Copy(_items, 0, _items, index, index); // Copy last part of _items back to inserted location Array.Copy(_items, index + count, _items, index * 2, _size - index); } else { c.CopyTo(_items, index); } _size += count; } } else if (index < _size) { // We're inserting a lazy enumerable. Call Insert on each of the constituent items. using (IEnumerator en = collection.GetEnumerator()) { while (en.MoveNext()) { Insert(index++, en.Current); } } } else { // We're adding a lazy enumerable because the index is at the end of this list. AddEnumerable(collection); } _version++; } // Returns the index of the last occurrence of a given value in a range of // this list. The list is searched backwards, starting at the end // and ending at the first element in the list. The elements of the list // are compared to the given value using the Object.Equals method. // // This method uses the Array.LastIndexOf method to perform the // search. // public int LastIndexOf(T item) { if (_size == 0) { // Special case for empty list return -1; } else { return LastIndexOf(item, _size - 1, _size); } } // Returns the index of the last occurrence of a given value in a range of // this list. The list is searched backwards, starting at index // index and ending at the first element in the list. The // elements of the list are compared to the given value using the // Object.Equals method. // // This method uses the Array.LastIndexOf method to perform the // search. // public int LastIndexOf(T item, int index) { return LastIndexOf(item, index, index + 1); } // Returns the index of the last occurrence of a given value in a range of // this list. The list is searched backwards, starting at index // index and upto count elements. The elements of // the list are compared to the given value using the Object.Equals // method. // // This method uses the Array.LastIndexOf method to perform the // search. // public int LastIndexOf(T item, int index, int count) { if (_size == 0) { // Special case for empty list return -1; } return Array.LastIndexOf(_items, item, index, count); } // Removes the element at the given index. The size of the list is // decreased by one. // public bool Remove(T item) { int index = IndexOf(item); if (index >= 0) { RemoveAt(index); return true; } return false; } void System.Collections.IList.Remove(Object item) { if (IsCompatibleObject(item)) { Remove((T)item); } } // This method removes all items which matches the predicate. // The complexity is O(n). public int RemoveAll(Predicate match) { int freeIndex = 0; // the first free slot in items array // Find the first item which needs to be removed. while (freeIndex < _size && !match(_items[freeIndex])) freeIndex++; if (freeIndex >= _size) return 0; int current = freeIndex + 1; while (current < _size) { // Find the first item which needs to be kept. while (current < _size && match(_items[current])) current++; if (current < _size) { // copy item to the free slot. _items[freeIndex++] = _items[current++]; } } if (!typeof(T).IsValueType) { Array.Clear(_items, freeIndex, _size - freeIndex); // Clear the elements so that the gc can reclaim the references. } int result = _size - freeIndex; _size = freeIndex; _version++; return result; } // Removes the element at the given index. The size of the list is // decreased by one. // public void RemoveAt(int index) { _size--; if (index < _size) { Array.Copy(_items, index + 1, _items, index, _size - index); } if (!typeof(T).IsValueType) { _items[_size] = default(T); } _version++; } // Removes a range of elements from this list. // public void RemoveRange(int index, int count) { if (count > 0) { int i = _size; _size -= count; if (index < _size) { Array.Copy(_items, index + count, _items, index, _size - index); } _version++; if (!typeof(T).IsValueType) { Array.Clear(_items, _size, count); } } } // Reverses the elements in this list. public void Reverse() { Reverse(0, Count); } // Reverses the elements in a range of this list. Following a call to this // method, an element in the range given by index and count // which was previously located at index i will now be located at // index index + (index + count - i - 1). // public void Reverse(int index, int count) { if (count > 1) { Array.Reverse(_items, index, count); } _version++; } // Sorts the elements in this list. Uses the default comparer and // Array.Sort. public void Sort() { Sort(0, Count, null); } // Sorts the elements in this list. Uses Array.Sort with the // provided comparer. public void Sort(IComparer comparer) { Sort(0, Count, comparer); } // Sorts the elements in a section of this list. The sort compares the // elements to each other using the given IComparer interface. If // comparer is null, the elements are compared to each other using // the IComparable interface, which in that case must be implemented by all // elements of the list. // // This method uses the Array.Sort method to sort the elements. // public void Sort(int index, int count, IComparer comparer) { if (count > 1) { Array.Sort(_items, index, count, comparer); } _version++; } public void Sort(Comparison comparison) { throw new NotImplementedException(); /*if (_size > 1) { ArraySortHelper.Sort(_items, 0, _size, comparison); } _version++;*/ } // ToArray returns an array containing the contents of the UncheckedList. // This requires copying the UncheckedList, which is an O(n) operation. public T[] ToArray() { if (_size == 0) { return _emptyArray; } T[] array = new T[_size]; Array.Copy(_items, 0, array, 0, _size); return array; } // Sets the capacity of this list to the size of the list. This method can // be used to minimize a list's memory overhead once it is known that no // new elements will be added to the list. To completely clear a list and // release all memory referenced by the list, execute the following // statements: // // list.Clear(); // list.TrimExcess(); // public void TrimExcess() { int threshold = (int)(((double)_items.Length) * 0.9); if (_size < threshold) { Capacity = _size; } } public bool TrueForAll(Predicate match) { for (int i = 0; i < _size; i++) { if (!match(_items[i])) { return false; } } return true; } private void AddEnumerable(IEnumerable enumerable) { Debug.Assert(enumerable != null); Debug.Assert(!(enumerable is ICollection), "We should have optimized for this beforehand."); using (IEnumerator en = enumerable.GetEnumerator()) { _version++; // Even if the enumerable has no items, we can update _version. while (en.MoveNext()) { // Capture Current before doing anything else. If this throws // an exception, we want to make a clean break. T current = en.Current; if (_size == _items.Length) { EnsureCapacity(_size + 1); } _items[_size++] = current; } } } public struct Enumerator : IEnumerator, System.Collections.IEnumerator { private UncheckedList list; private int index; private int version; private T current; internal Enumerator(UncheckedList list) { this.list = list; index = 0; version = list._version; current = default(T); } public void Dispose() { } public bool MoveNext() { UncheckedList localUncheckedList = list; if (version == localUncheckedList._version && ((uint)index < (uint)localUncheckedList._size)) { current = localUncheckedList._items[index]; index++; return true; } return MoveNextRare(); } private bool MoveNextRare() { index = list._size + 1; current = default(T); return false; } public T Current { get { return current; } } Object System.Collections.IEnumerator.Current { get { return Current; } } void System.Collections.IEnumerator.Reset() { index = 0; current = default(T); } } } } ================================================ FILE: ILRuntime/ILRuntime/Reflection/Extensions.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using Mono.Cecil; using ILRuntime.CLR.Method; using ILRuntime.CLR.TypeSystem; namespace ILRuntime.Reflection { static class Extensions { public static object CreateInstance(this CustomAttribute attribute, IType at, Runtime.Enviorment.AppDomain appdomain) { object ins; List param = null; if (at is ILType) { var it = (ILType)at; if (!attribute.HasConstructorArguments) ins = it.Instantiate(true); else { ins = it.Instantiate(false); if (param == null) param = new List(); param.Clear(); object[] p = new object[attribute.ConstructorArguments.Count]; for (int j = 0; j < attribute.ConstructorArguments.Count; j++) { var ca = attribute.ConstructorArguments[j]; param.Add(appdomain.GetType(ca.Type, null, null)); p[j] = ca.Value; } var ctor = it.GetConstructor(param); appdomain.Invoke(ctor, ins, p); } if (attribute.HasProperties) { object[] p = new object[1]; foreach (var j in attribute.Properties) { p[0] = j.Argument.Value; var setter = it.GetMethod("set_" + j.Name, 1); appdomain.Invoke(setter, ins, p); } } } else { param = new List(); object[] p = null; if (attribute.HasConstructorArguments) { p = new object[attribute.ConstructorArguments.Count]; for (int j = 0; j < attribute.ConstructorArguments.Count; j++) { var ca = attribute.ConstructorArguments[j]; param.Add(appdomain.GetType(ca.Type, null, null)); p[j] = ca.Value; } } ins = ((CLRMethod)at.GetConstructor(param)).ConstructorInfo.Invoke(p); if (attribute.HasProperties) { foreach (var j in attribute.Properties) { var prop = at.TypeForCLR.GetProperty(j.Name); prop.SetValue(ins, j.Argument.Value, null); } } } return ins; } } } ================================================ FILE: ILRuntime/ILRuntime/Reflection/ILRuntimeConstructorInfo.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Globalization; using ILRuntime.CLR.Method; using ILRuntime.CLR.TypeSystem; namespace ILRuntime.Reflection { public class ILRuntimeConstructorInfo : ConstructorInfo { ILMethod method; ILRuntimeParameterInfo[] parameters; public ILRuntimeConstructorInfo(ILMethod m) { method = m; parameters = new ILRuntimeParameterInfo[m.ParameterCount]; for(int i = 0; i < m.ParameterCount; i++) { parameters[i] = new ILRuntimeParameterInfo(m.Parameters[i]); } } internal ILMethod ILMethod { get { return method; } } public override MethodAttributes Attributes { get { return MethodAttributes.Public; } } public override Type DeclaringType { get { return method.DeclearingType.ReflectionType; } } public override RuntimeMethodHandle MethodHandle { get { throw new NotImplementedException(); } } public override string Name { get { return method.Name; } } public override Type ReflectedType { get { return method.DeclearingType.ReflectionType; } } public override object[] GetCustomAttributes(bool inherit) { throw new NotImplementedException(); } public override object[] GetCustomAttributes(Type attributeType, bool inherit) { throw new NotImplementedException(); } public override MethodImplAttributes GetMethodImplementationFlags() { throw new NotImplementedException(); } public override ParameterInfo[] GetParameters() { return parameters; } public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) { var res = ((ILType)method.DeclearingType).Instantiate(false); method.DeclearingType.AppDomain.Invoke(method, res, parameters); return res; } public override bool IsDefined(Type attributeType, bool inherit) { throw new NotImplementedException(); } public override object Invoke(BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) { var res = ((ILType)method.DeclearingType).Instantiate(false); method.DeclearingType.AppDomain.Invoke(method, res, parameters); return res; } } } ================================================ FILE: ILRuntime/ILRuntime/Reflection/ILRuntimeFieldInfo.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Globalization; using Mono.Cecil; using ILRuntime.CLR.Utils; using ILRuntime.CLR.TypeSystem; using ILRuntime.Runtime; using ILRuntime.Runtime.Stack; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; namespace ILRuntime.Reflection { public class ILRuntimeFieldInfo : FieldInfo { System.Reflection.FieldAttributes attr; ILRuntimeType dType; ILType ilType; IType fieldType; bool isStatic; int fieldIdx; string name; FieldDefinition definition; Runtime.Enviorment.AppDomain appdomain; object[] customAttributes; Type[] attributeTypes; public IType ILFieldType { get { return fieldType; } } public ILRuntimeFieldInfo(FieldDefinition def, ILRuntimeType declaredType, bool isStatic, int fieldIdx) { definition = def; this.name = def.Name; dType = declaredType; ilType = dType.ILType; appdomain = ilType.AppDomain; this.isStatic = isStatic; this.fieldIdx = fieldIdx; if (isStatic) attr |= System.Reflection.FieldAttributes.Static; if (def.IsPublic) { attr |= System.Reflection.FieldAttributes.Public; } else attr |= System.Reflection.FieldAttributes.Private; fieldType = isStatic ? ilType.StaticFieldTypes[fieldIdx] : ilType.FieldTypes[fieldIdx]; } public ILRuntimeFieldInfo(FieldDefinition def, ILRuntimeType declaredType, int fieldIdx, IType fieldType) { definition = def; this.name = def.Name; dType = declaredType; ilType = dType.ILType; appdomain = ilType.AppDomain; this.isStatic = false; this.fieldIdx = fieldIdx; if (isStatic) attr |= System.Reflection.FieldAttributes.Static; if (def.IsPublic) { attr |= System.Reflection.FieldAttributes.Public; } else attr |= System.Reflection.FieldAttributes.Private; this.fieldType = fieldType; } void InitializeCustomAttribute() { customAttributes = new object[definition.CustomAttributes.Count]; attributeTypes = new Type[customAttributes.Length]; for (int i = 0; i < definition.CustomAttributes.Count; i++) { var attribute = definition.CustomAttributes[i]; var at = appdomain.GetType(attribute.AttributeType, null, null); try { object ins = attribute.CreateInstance(at, appdomain); attributeTypes[i] = at.ReflectionType; customAttributes[i] = ins; } catch { attributeTypes[i] = typeof(Attribute); } } } public override System.Reflection.FieldAttributes Attributes { get { return attr; } } public override Type DeclaringType { get { return dType; } } public override RuntimeFieldHandle FieldHandle { get { throw new NotImplementedException(); } } public override Type FieldType { get { return fieldType.ReflectionType; } } public override string Name { get { return name; } } public override Type ReflectedType { get { return fieldType.ReflectionType; } } public override object[] GetCustomAttributes(bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); return customAttributes; } public override object[] GetCustomAttributes(Type attributeType, bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); List res = new List(); for (int i = 0; i < customAttributes.Length; i++) { if (attributeTypes[i] == attributeType) res.Add(customAttributes[i]); } return res.ToArray(); } public override object GetValue(object obj) { unsafe { StackObject esp; ILTypeInstance ins; if (isStatic) { ins = ilType.StaticInstance; } else { if (obj is ILTypeInstance) ins = (ILTypeInstance)obj; else ins = ((CrossBindingAdaptorType)obj).ILInstance; } return fieldType.TypeForCLR.CheckCLRTypes(ins[fieldIdx]); } } public override bool IsDefined(Type attributeType, bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); for (int i = 0; i < customAttributes.Length; i++) { if (attributeTypes[i] == attributeType) return true; } return false; } public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture) { unsafe { StackObject esp; if (value is CrossBindingAdaptorType) value = ((CrossBindingAdaptorType)value).ILInstance; ILTypeInstance ins; if (isStatic) { ins = ilType.StaticInstance; } else { if (obj is ILTypeInstance) ins = (ILTypeInstance)obj; else ins = ((CrossBindingAdaptorType)obj).ILInstance; } ins[fieldIdx] = value; } } } } ================================================ FILE: ILRuntime/ILRuntime/Reflection/ILRuntimeMethodInfo.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Globalization; using ILRuntime.CLR.Method; namespace ILRuntime.Reflection { public class ILRuntimeMethodInfo : MethodInfo { ILMethod method; ILRuntimeParameterInfo[] parameters; Mono.Cecil.MethodDefinition definition; ILRuntime.Runtime.Enviorment.AppDomain appdomain; object[] customAttributes; Type[] attributeTypes; public ILRuntimeMethodInfo(ILMethod m) { method = m; definition = m.Definition; appdomain = m.DeclearingType.AppDomain; parameters = new ILRuntimeParameterInfo[m.ParameterCount]; for (int i = 0; i < m.ParameterCount; i++) { parameters[i] = new ILRuntimeParameterInfo(m.Parameters[i]); } } void InitializeCustomAttribute() { customAttributes = new object[definition.CustomAttributes.Count]; attributeTypes = new Type[customAttributes.Length]; for (int i = 0; i < definition.CustomAttributes.Count; i++) { var attribute = definition.CustomAttributes[i]; var at = appdomain.GetType(attribute.AttributeType, null, null); try { object ins = attribute.CreateInstance(at, appdomain); attributeTypes[i] = at.ReflectionType; customAttributes[i] = ins; } catch { attributeTypes[i] = typeof(Attribute); } } } internal ILMethod ILMethod { get { return method; } } public override MethodAttributes Attributes { get { return MethodAttributes.Public; } } public override Type DeclaringType { get { return method.DeclearingType.ReflectionType; } } public override RuntimeMethodHandle MethodHandle { get { throw new NotImplementedException(); } } public override string Name { get { return method.Name; } } public override Type ReflectedType { get { return method.DeclearingType.ReflectionType; } } public override ICustomAttributeProvider ReturnTypeCustomAttributes { get { throw new NotImplementedException(); } } public override MethodInfo GetBaseDefinition() { return this; } public override object[] GetCustomAttributes(bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); return customAttributes; } public override object[] GetCustomAttributes(Type attributeType, bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); List res = new List(); for (int i = 0; i < customAttributes.Length; i++) { if (attributeTypes[i] == attributeType) res.Add(customAttributes[i]); } return res.ToArray(); } public override MethodImplAttributes GetMethodImplementationFlags() { throw new NotImplementedException(); } public override ParameterInfo[] GetParameters() { throw new NotImplementedException(); } public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) { if (method.HasThis) { var res = appdomain.Invoke(method, obj, parameters); return res; } else return appdomain.Invoke(method, null, parameters); } public override bool IsDefined(Type attributeType, bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); for (int i = 0; i < customAttributes.Length; i++) { if (attributeTypes[i] == attributeType) return true; } return false; } } } ================================================ FILE: ILRuntime/ILRuntime/Reflection/ILRuntimeParameterInfo.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Globalization; using ILRuntime.CLR.TypeSystem; namespace ILRuntime.Reflection { public class ILRuntimeParameterInfo : ParameterInfo { IType type; public ILRuntimeParameterInfo(IType type) { this.type = type; } public override Type ParameterType { get { return type.ReflectionType; } } } } ================================================ FILE: ILRuntime/ILRuntime/Reflection/ILRuntimePropertyInfo.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Globalization; using ILRuntime.CLR.Method; using ILRuntime.CLR.TypeSystem; namespace ILRuntime.Reflection { public class ILRuntimePropertyInfo : PropertyInfo { ILMethod getter, setter; ILType dType; Mono.Cecil.PropertyDefinition definition; ILRuntime.Runtime.Enviorment.AppDomain appdomain; object[] customAttributes; Type[] attributeTypes; static object[] param = new object[1]; public ILMethod Getter { get { return getter; } set { getter = value; } } public ILMethod Setter { get { return setter; } set { setter = value; } } public bool IsPublic { get { if (getter != null) return getter.Definition.IsPublic; else return setter.Definition.IsPublic; } } public bool IsStatic { get { if (getter != null) return getter.IsStatic; else return setter.IsStatic; } } public ILRuntimePropertyInfo(Mono.Cecil.PropertyDefinition definition, ILType dType) { this.definition = definition; this.dType = dType; appdomain = dType.AppDomain; } void InitializeCustomAttribute() { customAttributes = new object[definition.CustomAttributes.Count]; attributeTypes = new Type[customAttributes.Length]; for (int i = 0; i < definition.CustomAttributes.Count; i++) { var attribute = definition.CustomAttributes[i]; var at = appdomain.GetType(attribute.AttributeType, null, null); try { object ins = attribute.CreateInstance(at, appdomain); attributeTypes[i] = at.ReflectionType; customAttributes[i] = ins; } catch { attributeTypes[i] = typeof(Attribute); } } } public override string Name { get { return definition.Name; } } public override Type ReflectedType { get { return dType.ReflectionType; } } public override PropertyAttributes Attributes { get { return PropertyAttributes.None; } } public override bool CanRead { get { return getter != null; } } public override bool CanWrite { get { return setter != null; } } public override Type PropertyType { get { if (getter != null) return getter.ReturnType.ReflectionType; else { return setter.Parameters[0].ReflectionType; } } } public override Type DeclaringType { get { return dType.ReflectionType; } } public override object[] GetCustomAttributes(bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); return customAttributes; } public override object[] GetCustomAttributes(Type attributeType, bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); List res = new List(); for (int i = 0; i < customAttributes.Length; i++) { if (attributeTypes[i] == attributeType) res.Add(customAttributes[i]); } return res.ToArray(); } public override bool IsDefined(Type attributeType, bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); for (int i = 0; i < customAttributes.Length; i++) { if (attributeTypes[i] == attributeType) return true; } return false; } public override MethodInfo[] GetAccessors(bool nonPublic) { throw new NotImplementedException(); } public override MethodInfo GetGetMethod(bool nonPublic) { if (getter != null) return getter.ReflectionMethodInfo; return null; } public override ParameterInfo[] GetIndexParameters() { throw new NotImplementedException(); } public override MethodInfo GetSetMethod(bool nonPublic) { if (setter != null) return setter.ReflectionMethodInfo; return null; } public override object GetValue(object obj, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture) { return appdomain.Invoke(getter, obj, null); } public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture) { param[0] = value; appdomain.Invoke(setter, obj, param); } } } ================================================ FILE: ILRuntime/ILRuntime/Reflection/ILRuntimeType.cs ================================================ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection; using System.Text; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Intepreter; namespace ILRuntime.Reflection { public class ILRuntimeType : Type { ILType type; Runtime.Enviorment.AppDomain appdomain; object[] customAttributes; Type[] attributeTypes; ILRuntimeFieldInfo[] fields; ILRuntimePropertyInfo[] properties; ILRuntimeMethodInfo[] methods; public ILType ILType { get { return type; } } public ILRuntimeType(ILType t) { type = t; appdomain = t.AppDomain; } void InitializeCustomAttribute() { customAttributes = new object[type.TypeDefinition.CustomAttributes.Count]; attributeTypes = new Type[customAttributes.Length]; for (int i = 0; i < type.TypeDefinition.CustomAttributes.Count; i++) { var attribute = type.TypeDefinition.CustomAttributes[i]; var at = appdomain.GetType(attribute.AttributeType, type, null); try { object ins = attribute.CreateInstance(at, appdomain); attributeTypes[i] = at.ReflectionType is ILRuntimeWrapperType ? at.TypeForCLR : at.ReflectionType; customAttributes[i] = ins; } catch { attributeTypes[i] = typeof(Attribute); } } } void InitializeProperties() { int cnt = type.TypeDefinition.HasProperties ? type.TypeDefinition.Properties.Count : 0; properties = new ILRuntimePropertyInfo[cnt]; for (int i = 0; i < cnt; i++) { Mono.Cecil.PropertyDefinition pd = type.TypeDefinition.Properties[i]; ILRuntimePropertyInfo pi = new ILRuntimePropertyInfo(pd, type); properties[i] = pi; if (pd.GetMethod != null) pi.Getter = type.GetMethod(pd.GetMethod.Name, 0) as ILMethod; if (pd.SetMethod != null) pi.Setter = type.GetMethod(pd.SetMethod.Name, 1) as ILMethod; } } void InitializeMethods() { var methods = type.GetMethods(); this.methods = new ILRuntimeMethodInfo[methods.Count]; for(int i = 0; i < methods.Count; i++) { this.methods[i] = (ILRuntimeMethodInfo)((ILMethod)methods[i]).ReflectionMethodInfo; } } void InitializeFields() { int staticCnt = type.StaticFieldTypes != null ? type.StaticFieldTypes.Length : 0; fields = new ILRuntimeFieldInfo[type.TotalFieldCount + staticCnt]; for (int i = 0; i < type.TotalFieldCount; i++) { Mono.Cecil.FieldDefinition fd; var t = type.GetField(i, out fd); fields[i] = new ILRuntimeFieldInfo(fd, this, i, t); } for (int i = type.TotalFieldCount; i < type.TotalFieldCount + staticCnt; i++) { fields[i] = new ILRuntimeFieldInfo(type.StaticFieldDefinitions[i - type.TotalFieldCount], this, true, i - type.TotalFieldCount); } } public override Assembly Assembly { get { return typeof(ILRuntimeType).Assembly; } } public override string AssemblyQualifiedName { get { return type.FullName; } } public override Type BaseType { get { return type.BaseType != null ? type.BaseType.ReflectionType : null; } } public override string FullName { get { return type.FullName; } } public override Guid GUID { get { throw new NotImplementedException(); } } public override Module Module { get { throw new NotImplementedException(); } } public override string Name { get { return type.Name; } } public override string Namespace { get { throw new NotImplementedException(); } } public override Type UnderlyingSystemType { get { return typeof(ILTypeInstance); } } public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) { var ctors = type.GetConstructors(); ConstructorInfo[] res = new ConstructorInfo[ctors.Count]; for(int i = 0; i < res.Length; i++) { res[i] = ctors[i].ReflectionConstructorInfo; } return res; } public override object[] GetCustomAttributes(bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); return customAttributes; } public override object[] GetCustomAttributes(Type attributeType, bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); List res = new List(); for(int i = 0; i < customAttributes.Length; i++) { if (attributeTypes[i] == attributeType) res.Add(customAttributes[i]); } return res.ToArray(); } public override Type GetElementType() { if (type.IsArray) { return type.ElementType.ReflectionType; } else throw new NotImplementedException(); } public override EventInfo GetEvent(string name, BindingFlags bindingAttr) { throw new NotImplementedException(); } public override EventInfo[] GetEvents(BindingFlags bindingAttr) { throw new NotImplementedException(); } public override FieldInfo GetField(string name, BindingFlags bindingAttr) { if (fields == null) InitializeFields(); foreach(var i in fields) { if (i.Name == name) return i; } return null; } public override FieldInfo[] GetFields(BindingFlags bindingAttr) { if (fields == null) InitializeFields(); bool isPublic = (bindingAttr & BindingFlags.Public) == BindingFlags.Public; bool isPrivate = (bindingAttr & BindingFlags.NonPublic) == BindingFlags.NonPublic; bool isStatic = (bindingAttr & BindingFlags.Static) == BindingFlags.Static; bool isInstance = (bindingAttr & BindingFlags.Instance) == BindingFlags.Instance; List res = new List(); foreach(var i in fields) { if (isPublic != i.IsPublic && isPrivate != !i.IsPublic) continue; if ((isStatic != i.IsStatic) && (isInstance != !i.IsStatic)) continue; res.Add(i); } return res.ToArray(); } public override Type GetInterface(string name, bool ignoreCase) { if (type.FirstCLRInterface != null) { if (type.FirstCLRInterface.Name == name) return type.FirstCLRInterface.TypeForCLR; else return null; } else return null; } public override Type[] GetInterfaces() { if (type.FirstCLRInterface != null) return new Type[] { type.FirstCLRInterface.TypeForCLR }; else return new Type[0]; } public override MemberInfo[] GetMembers(BindingFlags bindingAttr) { if (methods == null) InitializeMethods(); if (fields == null) InitializeFields(); if (properties == null) InitializeProperties(); MemberInfo[] res = new MemberInfo[methods.Length + fields.Length + properties.Length]; for (int i = 0; i < methods.Length; i++) { res[i] = methods[i]; } for (int i = methods.Length; i < methods.Length + fields.Length; i++) { res[i] = fields[i - methods.Length]; } for (int i = methods.Length + fields.Length; i < res.Length; i++) { res[i] = properties[i- methods.Length - fields.Length]; } return res; } public override MethodInfo[] GetMethods(BindingFlags bindingAttr) { if (methods == null) InitializeMethods(); return methods; } public override Type GetNestedType(string name, BindingFlags bindingAttr) { throw new NotImplementedException(); } public override Type[] GetNestedTypes(BindingFlags bindingAttr) { throw new NotImplementedException(); } public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) { if (properties == null) InitializeProperties(); bool isPublic = (bindingAttr & BindingFlags.Public) == BindingFlags.Public; bool isPrivate = (bindingAttr & BindingFlags.NonPublic) == BindingFlags.NonPublic; bool isStatic = (bindingAttr & BindingFlags.Static) == BindingFlags.Static; bool isInstance = (bindingAttr & BindingFlags.Instance) == BindingFlags.Instance; List res = new List(); foreach (var i in properties) { if (isPublic != i.IsPublic && isPrivate != !i.IsPublic) continue; if ((isStatic != i.IsStatic) && (isInstance != !i.IsStatic)) continue; res.Add(i); } return res.ToArray(); } public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters) { throw new NotImplementedException(); } public override bool IsDefined(Type attributeType, bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); for (int i = 0; i < customAttributes.Length; i++) { if (attributeTypes[i] == attributeType) return true; } return false; } protected override TypeAttributes GetAttributeFlagsImpl() { TypeAttributes res = TypeAttributes.Public; if (type.TypeDefinition.IsAbstract) res |= TypeAttributes.Abstract; if (!type.IsValueType) res |= TypeAttributes.Class; if (type.TypeDefinition.IsSealed) res |= TypeAttributes.Sealed; return res; } protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) { List param = new List(); for (int i = 0; i < types.Length; i++) { if (types[i] is ILRuntimeType) param.Add(((ILRuntimeType)types[i]).type); else { var t = appdomain.GetType(types[i]); if (t == null) t = appdomain.GetType(types[i].AssemblyQualifiedName); if (t == null) throw new TypeLoadException(); param.Add(t); } } var res = type.GetConstructor(param); if (res != null) return ((ILMethod)res).ReflectionConstructorInfo; else return null; } protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) { IMethod res; if (types == null) res = type.GetMethod(name); else { List param = new List(); for (int i = 0; i < types.Length; i++) { if (types[i] is ILRuntimeType) param.Add(((ILRuntimeType)types[i]).type); else { var t = appdomain.GetType(types[i]); if (t == null) t = appdomain.GetType(types[i].AssemblyQualifiedName); if (t == null) throw new TypeLoadException(); param.Add(t); } } bool declearedOnly = (bindingAttr & BindingFlags.DeclaredOnly) == BindingFlags.DeclaredOnly; res = type.GetMethod(name, param, null, null, declearedOnly); } if (res != null) return ((ILMethod)res).ReflectionMethodInfo; else return null; } protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) { if (properties == null) InitializeProperties(); foreach(var i in properties) { if (i.Name == name) return i; } return null; } protected override bool HasElementTypeImpl() { return false; } protected override bool IsArrayImpl() { return type.IsArray; } protected override bool IsByRefImpl() { return false; } protected override bool IsCOMObjectImpl() { return false; } protected override bool IsPointerImpl() { return false; } protected override bool IsPrimitiveImpl() { return false; } public override int GetHashCode() { return type.GetHashCode(); } public override bool Equals(object o) { return o is ILRuntimeType ? ((ILRuntimeType)o).type == type : false; } public override bool IsGenericType { get { return type.HasGenericParameter; } } public override bool IsGenericTypeDefinition { get { return type.HasGenericParameter; } } } } ================================================ FILE: ILRuntime/ILRuntime/Reflection/ILRuntimeWrapperType.cs ================================================ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection; using System.Text; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Intepreter; namespace ILRuntime.Reflection { public class ILRuntimeWrapperType : Type { CLRType type; Type et; public CLRType CLRType { get { return type; } } public Type RealType { get { return et; } } public override Guid GUID { get { return et.GUID; } } public override Module Module { get { return et.Module; } } public override Assembly Assembly { get { return et.Assembly; } } public override string FullName { get { return et.FullName; } } public override string Namespace { get { return et.Namespace; } } public override string AssemblyQualifiedName { get { return et.AssemblyQualifiedName; } } public override Type BaseType { get { return et.BaseType; } } public override Type UnderlyingSystemType { get { return et.UnderlyingSystemType; } } public override string Name { get { return et.Name; } } public ILRuntimeWrapperType(CLRType t) { type = t; et = t.TypeForCLR; } public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters) { return et.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters); } protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) { return et.GetConstructor(bindingAttr, binder, callConvention, types, modifiers); } public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) { return et.GetConstructors(bindingAttr); } protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) { return et.GetMethod(name, bindingAttr, binder, callConvention, types, modifiers); } public override MethodInfo[] GetMethods(BindingFlags bindingAttr) { return et.GetMethods(bindingAttr); } public override FieldInfo GetField(string name, BindingFlags bindingAttr) { return et.GetField(name, bindingAttr); } public override FieldInfo[] GetFields(BindingFlags bindingAttr) { return et.GetFields(bindingAttr); } public override Type GetInterface(string name, bool ignoreCase) { return et.GetInterface(name, ignoreCase); } public override Type[] GetInterfaces() { return et.GetInterfaces(); } public override EventInfo GetEvent(string name, BindingFlags bindingAttr) { return et.GetEvent(name, bindingAttr); } public override EventInfo[] GetEvents(BindingFlags bindingAttr) { return et.GetEvents(bindingAttr); } protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) { return et.GetProperty(name, bindingAttr, binder, returnType, types, modifiers); } public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) { return et.GetProperties(bindingAttr); } public override Type[] GetNestedTypes(BindingFlags bindingAttr) { return et.GetNestedTypes(bindingAttr); } public override int GetHashCode() { return type.GetHashCode(); } public override Type GetNestedType(string name, BindingFlags bindingAttr) { return et.GetNestedType(name, bindingAttr); } public override MemberInfo[] GetMembers(BindingFlags bindingAttr) { return et.GetMembers(bindingAttr); } protected override TypeAttributes GetAttributeFlagsImpl() { return et.Attributes; } protected override bool IsArrayImpl() { return et.IsArray; } protected override bool IsByRefImpl() { return et.IsByRef; } protected override bool IsPointerImpl() { return et.IsPointer; } protected override bool IsPrimitiveImpl() { return et.IsPrimitive; } protected override bool IsCOMObjectImpl() { return et.IsCOMObject; } public override Type GetElementType() { return et.GetElementType(); } protected override bool HasElementTypeImpl() { return et.HasElementType; } public override object[] GetCustomAttributes(bool inherit) { return et.GetCustomAttributes(inherit); } public override object[] GetCustomAttributes(Type attributeType, bool inherit) { return et.GetCustomAttributes(attributeType, inherit); } public override bool IsDefined(Type attributeType, bool inherit) { return et.IsDefined(attributeType, inherit); } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Adaptors/CLRCrossBindingAdaptors.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; namespace ILRuntime.Runtime.Adaptors { class AttributeAdaptor : CrossBindingAdaptor { public override Type AdaptorType { get { return typeof(Adaptor); } } public override Type BaseCLRType { get { return typeof(Attribute); } } public override object CreateCLRInstance(Enviorment.AppDomain appdomain, ILTypeInstance instance) { return new Adaptor(appdomain, instance); } class Adaptor : Attribute, CrossBindingAdaptorType { ILTypeInstance instance; ILRuntime.Runtime.Enviorment.AppDomain appdomain; bool isToStringGot; IMethod toString; public Adaptor(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance) { this.appdomain = appdomain; this.instance = instance; } public ILTypeInstance ILInstance { get { return instance; } } public override string ToString() { if (!isToStringGot) { isToStringGot = true; IMethod m = appdomain.ObjectType.GetMethod("ToString", 0); toString = instance.Type.GetVirtualMethod(m); } if (toString == null || toString is ILMethod) { return instance.ToString(); } else return instance.Type.FullName; } } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/CLRBinding/BindingCodeGenerator.cs ================================================ using System; using System.Collections.Generic; using System.Reflection; using System.Linq; using System.Text; using ILRuntime.Runtime.Enviorment; using ILRuntime.Other; namespace ILRuntime.Runtime.CLRBinding { public class BindingCodeGenerator { public static void GenerateBindingCode(List types, string outputPath, HashSet excludeMethods = null, HashSet excludeFields = null) { if (!System.IO.Directory.Exists(outputPath)) System.IO.Directory.CreateDirectory(outputPath); string[] oldFiles = System.IO.Directory.GetFiles(outputPath, "*.cs"); foreach (var i in oldFiles) { System.IO.File.Delete(i); } List clsNames = new List(); foreach (var i in types) { string clsName, realClsName; bool isByRef; if (i.GetCustomAttributes(typeof(ObsoleteAttribute), true).Length > 0) continue; i.GetClassName(out clsName, out realClsName, out isByRef); clsNames.Add(clsName); using (System.IO.StreamWriter sw = new System.IO.StreamWriter(outputPath + "/" + clsName + ".cs", false, Encoding.UTF8)) { sw.Write(@"using System; using System.Collections.Generic; using System.Reflection; using System.Runtime.InteropServices; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Stack; using ILRuntime.Reflection; using ILRuntime.CLR.Utils; namespace ILRuntime.Runtime.Generated { unsafe class "); sw.WriteLine(clsName); sw.Write(@" { public static void Register(ILRuntime.Runtime.Enviorment.AppDomain app) { BindingFlags flag = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; MethodBase method; FieldInfo field; Type[] args; Type type = typeof("); sw.Write(realClsName); sw.WriteLine(");"); MethodInfo[] methods = i.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly); FieldInfo[] fields = i.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly); string registerMethodCode = i.GenerateMethodRegisterCode(methods, excludeMethods); string registerFieldCode = i.GenerateFieldRegisterCode(fields, excludeFields); string registerValueTypeCode = i.GenerateValueTypeRegisterCode(realClsName); string registerMiscCode = i.GenerateMiscRegisterCode(realClsName, true, true); string commonCode = i.GenerateCommonCode(realClsName); ConstructorInfo[] ctors = i.GetConstructors(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly); string ctorRegisterCode = i.GenerateConstructorRegisterCode(ctors, excludeMethods); string methodWraperCode = i.GenerateMethodWraperCode(methods, realClsName, excludeMethods); string fieldWraperCode = i.GenerateFieldWraperCode(fields, realClsName, excludeFields); string cloneWraperCode = i.GenerateCloneWraperCode(fields, realClsName); string ctorWraperCode = i.GenerateConstructorWraperCode(ctors, realClsName, excludeMethods); sw.WriteLine(registerMethodCode); sw.WriteLine(registerFieldCode); sw.WriteLine(registerValueTypeCode); sw.WriteLine(registerMiscCode); sw.WriteLine(ctorRegisterCode); sw.WriteLine(" }"); sw.WriteLine(); sw.WriteLine(commonCode); sw.WriteLine(methodWraperCode); sw.WriteLine(fieldWraperCode); sw.WriteLine(cloneWraperCode); sw.WriteLine(ctorWraperCode); sw.WriteLine(" }"); sw.WriteLine("}"); sw.Flush(); } } using (System.IO.StreamWriter sw = new System.IO.StreamWriter(outputPath + "/CLRBindings.cs", false, Encoding.UTF8)) { sw.WriteLine(@"using System; using System.Collections.Generic; using System.Reflection; namespace ILRuntime.Runtime.Generated { class CLRBindings { /// /// Initialize the CLR binding, please invoke this AFTER CLR Redirection registration /// public static void Initialize(ILRuntime.Runtime.Enviorment.AppDomain app) {"); foreach (var i in clsNames) { sw.Write(" "); sw.Write(i); sw.WriteLine(".Register(app);"); } sw.WriteLine(@" } } }"); } } class CLRBindingGenerateInfo { public Type Type { get; set; } public HashSet Methods { get; set; } public HashSet Fields { get; set; } public HashSet Constructors { get; set; } public bool ArrayNeeded { get; set; } public bool DefaultInstanceNeeded { get; set; } public bool ValueTypeNeeded { get; set; } public bool NeedGenerate { get { if (Methods.Count == 0 && Constructors.Count == 0 && Fields.Count == 0 && !ArrayNeeded && !DefaultInstanceNeeded && !ValueTypeNeeded) return false; else { //Making CLRBinding for such types makes no sense if (Type == typeof(Delegate) || Type == typeof(System.Runtime.CompilerServices.RuntimeHelpers)) return false; return true; } } } } public static void GenerateBindingCode(ILRuntime.Runtime.Enviorment.AppDomain domain, string outputPath) { if (domain == null) return; if (!System.IO.Directory.Exists(outputPath)) System.IO.Directory.CreateDirectory(outputPath); Dictionary infos = new Dictionary(new ByReferenceKeyComparer()); CrawlAppdomain(domain, infos); string[] oldFiles = System.IO.Directory.GetFiles(outputPath, "*.cs"); foreach (var i in oldFiles) { System.IO.File.Delete(i); } HashSet excludeMethods = null; HashSet excludeFields = null; List clsNames = new List(); foreach (var info in infos) { if (!info.Value.NeedGenerate) continue; Type i = info.Value.Type; string clsName, realClsName; bool isByRef; if (i.GetCustomAttributes(typeof(ObsoleteAttribute), true).Length > 0) continue; i.GetClassName(out clsName, out realClsName, out isByRef); clsNames.Add(clsName); using (System.IO.StreamWriter sw = new System.IO.StreamWriter(outputPath + "/" + clsName + ".cs", false, Encoding.UTF8)) { sw.Write(@"using System; using System.Collections.Generic; using System.Reflection; using System.Runtime.InteropServices; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Stack; using ILRuntime.Reflection; using ILRuntime.CLR.Utils; namespace ILRuntime.Runtime.Generated { unsafe class "); sw.WriteLine(clsName); sw.Write(@" { public static void Register(ILRuntime.Runtime.Enviorment.AppDomain app) { BindingFlags flag = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; MethodBase method; FieldInfo field; Type[] args; Type type = typeof("); sw.Write(realClsName); sw.WriteLine(");"); MethodInfo[] methods = info.Value.Methods.ToArray(); FieldInfo[] fields = info.Value.Fields.ToArray(); string registerMethodCode = i.GenerateMethodRegisterCode(methods, excludeMethods); string registerFieldCode = fields.Length > 0 ? i.GenerateFieldRegisterCode(fields, excludeFields) : null; string registerValueTypeCode = info.Value.ValueTypeNeeded ? i.GenerateValueTypeRegisterCode(realClsName) : null; string registerMiscCode = i.GenerateMiscRegisterCode(realClsName, info.Value.DefaultInstanceNeeded, info.Value.ArrayNeeded); string commonCode = i.GenerateCommonCode(realClsName); ConstructorInfo[] ctors = info.Value.Constructors.ToArray(); string ctorRegisterCode = i.GenerateConstructorRegisterCode(ctors, excludeMethods); string methodWraperCode = i.GenerateMethodWraperCode(methods, realClsName, excludeMethods); string fieldWraperCode = fields.Length > 0 ? i.GenerateFieldWraperCode(fields, realClsName, excludeFields) : null; string cloneWraperCode = null; if (info.Value.ValueTypeNeeded) { //Memberwise clone should copy all fields var fs = i.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly); cloneWraperCode = i.GenerateCloneWraperCode(fs, realClsName); } string ctorWraperCode = i.GenerateConstructorWraperCode(ctors, realClsName, excludeMethods); sw.WriteLine(registerMethodCode); if (fields.Length > 0) sw.WriteLine(registerFieldCode); if (info.Value.ValueTypeNeeded) sw.WriteLine(registerValueTypeCode); if (!string.IsNullOrEmpty(registerMiscCode)) sw.WriteLine(registerMiscCode); sw.WriteLine(ctorRegisterCode); sw.WriteLine(" }"); sw.WriteLine(); sw.WriteLine(commonCode); sw.WriteLine(methodWraperCode); if (fields.Length > 0) sw.WriteLine(fieldWraperCode); if (info.Value.ValueTypeNeeded) sw.WriteLine(cloneWraperCode); sw.WriteLine(ctorWraperCode); sw.WriteLine(" }"); sw.WriteLine("}"); sw.Flush(); } } using (System.IO.StreamWriter sw = new System.IO.StreamWriter(outputPath + "/CLRBindings.cs", false, Encoding.UTF8)) { sw.WriteLine(@"using System; using System.Collections.Generic; using System.Reflection; namespace ILRuntime.Runtime.Generated { class CLRBindings { /// /// Initialize the CLR binding, please invoke this AFTER CLR Redirection registration /// public static void Initialize(ILRuntime.Runtime.Enviorment.AppDomain app) {"); foreach (var i in clsNames) { sw.Write(" "); sw.Write(i); sw.WriteLine(".Register(app);"); } sw.WriteLine(@" } } }"); } } static void CrawlAppdomain(ILRuntime.Runtime.Enviorment.AppDomain domain, Dictionary infos) { var arr = domain.LoadedTypes.Values.ToArray(); //Prewarm foreach (var type in arr) { if (type is CLR.TypeSystem.ILType) { if (type.HasGenericParameter) continue; var methods = type.GetMethods().ToList(); foreach (var i in ((CLR.TypeSystem.ILType)type).GetConstructors()) methods.Add(i); if (((CLR.TypeSystem.ILType)type).GetStaticConstroctor() != null) methods.Add(((CLR.TypeSystem.ILType)type).GetStaticConstroctor()); foreach (var j in methods) { CLR.Method.ILMethod method = j as CLR.Method.ILMethod; if (method != null) { if (method.GenericParameterCount > 0 && !method.IsGenericInstance) continue; var body = method.Body; } } } } arr = domain.LoadedTypes.Values.ToArray(); foreach (var type in arr) { if (type is CLR.TypeSystem.ILType) { if (type.HasGenericParameter) continue; var methods = type.GetMethods().ToList(); foreach (var i in ((CLR.TypeSystem.ILType)type).GetConstructors()) methods.Add(i); foreach (var j in methods) { CLR.Method.ILMethod method = j as CLR.Method.ILMethod; if (method != null) { if (method.GenericParameterCount > 0 && !method.IsGenericInstance) continue; var body = method.Body; foreach (var ins in body) { switch (ins.Code) { case Intepreter.OpCodes.OpCodeEnum.Newobj: { CLR.Method.CLRMethod m = domain.GetMethod(ins.TokenInteger) as CLR.Method.CLRMethod; if (m != null) { if (m.DeclearingType.IsDelegate) continue; Type t = m.DeclearingType.TypeForCLR; CLRBindingGenerateInfo info; if (!infos.TryGetValue(t, out info)) { info = CreateNewBindingInfo(t); infos[t] = info; } if (m.IsConstructor) info.Constructors.Add(m.ConstructorInfo); else info.Methods.Add(m.MethodInfo); } } break; case Intepreter.OpCodes.OpCodeEnum.Ldfld: case Intepreter.OpCodes.OpCodeEnum.Stfld: case Intepreter.OpCodes.OpCodeEnum.Ldflda: case Intepreter.OpCodes.OpCodeEnum.Ldsfld: case Intepreter.OpCodes.OpCodeEnum.Ldsflda: case Intepreter.OpCodes.OpCodeEnum.Stsfld: { var t = domain.GetType((int)(ins.TokenLong >> 32)) as CLR.TypeSystem.CLRType; if(t != null) { var fi = t.GetField((int)ins.TokenLong); if (fi != null && fi.IsPublic) { CLRBindingGenerateInfo info; if (!infos.TryGetValue(t.TypeForCLR, out info)) { info = CreateNewBindingInfo(t.TypeForCLR); infos[t.TypeForCLR] = info; } if(ins.Code == Intepreter.OpCodes.OpCodeEnum.Stfld || ins.Code == Intepreter.OpCodes.OpCodeEnum.Stsfld) { if (t.IsValueType) { info.ValueTypeNeeded = true; info.DefaultInstanceNeeded = true; } } if (t.TypeForCLR.CheckCanPinn() || !t.IsValueType) info.Fields.Add(fi); } } } break; case Intepreter.OpCodes.OpCodeEnum.Ldtoken: { if (ins.TokenInteger == 0) { var t = domain.GetType((int)(ins.TokenLong >> 32)) as CLR.TypeSystem.CLRType; if (t != null) { var fi = t.GetField((int)ins.TokenLong); if (fi != null) { CLRBindingGenerateInfo info; if (!infos.TryGetValue(t.TypeForCLR, out info)) { info = CreateNewBindingInfo(t.TypeForCLR); infos[t.TypeForCLR] = info; } info.Fields.Add(fi); } } } } break; case Intepreter.OpCodes.OpCodeEnum.Newarr: { var t = domain.GetType(ins.TokenInteger) as CLR.TypeSystem.CLRType; if(t != null) { CLRBindingGenerateInfo info; if (!infos.TryGetValue(t.TypeForCLR, out info)) { info = CreateNewBindingInfo(t.TypeForCLR); infos[t.TypeForCLR] = info; } info.ArrayNeeded = true; } } break; case Intepreter.OpCodes.OpCodeEnum.Call: case Intepreter.OpCodes.OpCodeEnum.Callvirt: { CLR.Method.CLRMethod m = domain.GetMethod(ins.TokenInteger) as CLR.Method.CLRMethod; if (m != null) { //Cannot explicit call base class's constructor directly if (m.IsConstructor) continue; if (!m.MethodInfo.IsPublic) continue; Type t = m.DeclearingType.TypeForCLR; CLRBindingGenerateInfo info; if (!infos.TryGetValue(t, out info)) { info = CreateNewBindingInfo(t); infos[t] = info; } info.Methods.Add(m.MethodInfo); } } break; } } } } } } } static CLRBindingGenerateInfo CreateNewBindingInfo(Type t) { CLRBindingGenerateInfo info = new CLRBindingGenerateInfo(); info.Type = t; info.Methods = new HashSet(); info.Fields = new HashSet(); info.Constructors = new HashSet(); return info; } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/CLRBinding/BindingGeneratorExtensions.cs ================================================ using System; using System.Collections.Generic; using System.Reflection; using System.Linq; using System.Text; using ILRuntime.Runtime.Enviorment; namespace ILRuntime.Runtime.CLRBinding { static class BindingGeneratorExtensions { internal static bool ShouldSkipField(this Type type, FieldInfo i) { if (i.IsPrivate) return true; //EventHandler is currently not supported if (i.IsSpecialName) { return true; } if (i.GetCustomAttributes(typeof(ObsoleteAttribute), true).Length > 0) return true; return false; } internal static bool ShouldSkipMethod(this Type type, MethodBase i) { if (i.IsPrivate) return true; if (i.IsGenericMethod) return true; //EventHandler is currently not supported var param = i.GetParameters(); if (i.IsSpecialName) { string[] t = i.Name.Split('_'); if (t[0] == "add" || t[0] == "remove") return true; if (t[0] == "get" || t[0] == "set") { Type[] ts; if (t[1] == "Item") { var cnt = t[0] == "set" ? param.Length - 1 : param.Length; ts = new Type[cnt]; for (int j = 0; j < cnt; j++) { ts[j] = param[j].ParameterType; } } else ts = new Type[0]; var prop = type.GetProperty(t[1], ts); if (prop == null) { return true; } if (prop.GetCustomAttributes(typeof(ObsoleteAttribute), true).Length > 0) return true; } } if (i.GetCustomAttributes(typeof(ObsoleteAttribute), true).Length > 0) return true; foreach (var j in param) { if (j.ParameterType.IsPointer) return true; } return false; } internal static void AppendParameters(this ParameterInfo[] param, StringBuilder sb) { bool first = true; foreach (var j in param) { if (first) first = false; else sb.Append(", "); if (j.IsOut && j.ParameterType.IsByRef) sb.Append("out "); else if (j.ParameterType.IsByRef) sb.Append("ref "); sb.Append(j.Name); } } internal static string GetRetrieveValueCode(this Type type, string realClsName) { if (type.IsByRef) type = type.GetElementType(); if (type.IsPrimitive) { if (type == typeof(int)) { return "ptr_of_this_method->Value"; } else if (type == typeof(long)) { return "*(long*)&ptr_of_this_method->Value"; } else if (type == typeof(short)) { return "(short)ptr_of_this_method->Value"; } else if (type == typeof(bool)) { return "ptr_of_this_method->Value == 1"; } else if (type == typeof(ushort)) { return "(ushort)ptr_of_this_method->Value"; } else if (type == typeof(float)) { return "*(float*)&ptr_of_this_method->Value"; } else if (type == typeof(double)) { return "*(double*)&ptr_of_this_method->Value"; } else if (type == typeof(byte)) { return "(byte)ptr_of_this_method->Value"; } else if (type == typeof(sbyte)) { return "(sbyte)ptr_of_this_method->Value"; } else if (type == typeof(uint)) { return "(uint)ptr_of_this_method->Value"; } else if (type == typeof(char)) { return "(char)ptr_of_this_method->Value"; } else if (type == typeof(ulong)) { return "*(ulong*)&ptr_of_this_method->Value"; } else throw new NotImplementedException(); } else { return string.Format("({0})typeof({0}).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack))", realClsName); } } internal static void GetRefWriteBackValueCode(this Type type, StringBuilder sb, string paramName) { if (type.IsPrimitive) { if (type == typeof(int)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;"); sb.Append(" ___dst->Value = " + paramName); sb.AppendLine(";"); } else if (type == typeof(long)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Long;"); sb.Append(" *(long*)&___dst->Value = " + paramName); sb.AppendLine(";"); } else if (type == typeof(short)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;"); sb.Append(" ___dst->Value = " + paramName); sb.AppendLine(";"); } else if (type == typeof(bool)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;"); sb.Append(" ___dst->Value = " + paramName + " ? 1 : 0;"); sb.AppendLine(";"); } else if (type == typeof(ushort)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;"); sb.Append(" ___dst->Value = " + paramName); sb.AppendLine(";"); } else if (type == typeof(float)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Float;"); sb.Append(" *(float*)&___dst->Value = " + paramName); sb.AppendLine(";"); } else if (type == typeof(double)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Double;"); sb.Append(" *(double*)&___dst->Value = " + paramName); sb.AppendLine(";"); } else if (type == typeof(byte)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;"); sb.Append(" ___dst->Value = " + paramName); sb.AppendLine(";"); } else if (type == typeof(sbyte)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;"); sb.Append(" ___dst->Value = " + paramName); sb.AppendLine(";"); } else if (type == typeof(uint)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;"); sb.Append(" ___dst->Value = (int)" + paramName); sb.AppendLine(";"); } else if (type == typeof(char)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;"); sb.Append(" ___dst->Value = (int)" + paramName); sb.AppendLine(";"); } else if (type == typeof(ulong)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Long;"); sb.Append(" *(ulong*)&___dst->Value = " + paramName); sb.AppendLine(";"); } else throw new NotImplementedException(); } else { if (!type.IsValueType) { sb.Append(@" object ___obj = "); sb.Append(paramName); sb.AppendLine(";"); sb.AppendLine(@" if (___obj is CrossBindingAdaptorType) ___obj = ((CrossBindingAdaptorType)___obj).ILInstance; __mStack[___dst->Value] = ___obj; "); } else { sb.Append(" __mStack[___dst->Value] = "); sb.Append(paramName); sb.AppendLine(";"); } } } internal static void GetReturnValueCode(this Type type, StringBuilder sb) { if (type.IsPrimitive) { if (type == typeof(int)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;"); sb.AppendLine(" __ret->Value = result_of_this_method;"); } else if (type == typeof(long)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Long;"); sb.AppendLine(" *(long*)&__ret->Value = result_of_this_method;"); } else if (type == typeof(short)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;"); sb.AppendLine(" __ret->Value = result_of_this_method;"); } else if (type == typeof(bool)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;"); sb.AppendLine(" __ret->Value = result_of_this_method ? 1 : 0;"); } else if (type == typeof(ushort)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;"); sb.AppendLine(" __ret->Value = result_of_this_method;"); } else if (type == typeof(float)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Float;"); sb.AppendLine(" *(float*)&__ret->Value = result_of_this_method;"); } else if (type == typeof(double)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Double;"); sb.AppendLine(" *(double*)&__ret->Value = result_of_this_method;"); } else if (type == typeof(byte)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;"); sb.AppendLine(" __ret->Value = result_of_this_method;"); } else if (type == typeof(sbyte)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;"); sb.AppendLine(" __ret->Value = result_of_this_method;"); } else if (type == typeof(uint)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;"); sb.AppendLine(" __ret->Value = (int)result_of_this_method;"); } else if (type == typeof(char)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;"); sb.AppendLine(" __ret->Value = (int)result_of_this_method;"); } else if (type == typeof(ulong)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Long;"); sb.AppendLine(" *(ulong*)&__ret->Value = result_of_this_method;"); } else throw new NotImplementedException(); sb.AppendLine(" return __ret + 1;"); } else { if (!type.IsSealed && type != typeof(ILRuntime.Runtime.Intepreter.ILTypeInstance)) { sb.AppendLine(@" object obj_result_of_this_method = result_of_this_method; if(obj_result_of_this_method is CrossBindingAdaptorType) { return ILIntepreter.PushObject(__ret, __mStack, ((CrossBindingAdaptorType)obj_result_of_this_method).ILInstance); }"); } sb.AppendLine(" return ILIntepreter.PushObject(__ret, __mStack, result_of_this_method);"); } } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/CLRBinding/CommonBindingGenerator.cs ================================================ using System; using System.Collections.Generic; using System.Reflection; using System.Linq; using System.Text; using ILRuntime.Runtime.Enviorment; namespace ILRuntime.Runtime.CLRBinding { static class CommonBindingGenerator { internal static string GenerateMiscRegisterCode(this Type type, string typeClsName, bool defaultCtor, bool newArr) { StringBuilder sb = new StringBuilder(); if (defaultCtor && !type.IsPrimitive && !type.IsAbstract) { var constructorFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; var hasDefaultConstructor = type.GetConstructor(constructorFlags, null, new Type[0], null) != null; if (hasDefaultConstructor || type.IsValueType) { sb.AppendLine(string.Format(" app.RegisterCLRCreateDefaultInstance(type, () => new {0}());", typeClsName)); } } if (newArr) { if (!type.IsAbstract || !type.IsSealed) { sb.AppendLine(string.Format(" app.RegisterCLRCreateArrayInstance(type, s => new {0}[s]);", typeClsName)); } } return sb.ToString(); } internal static string GenerateCommonCode(this Type type, string typeClsName) { if (!type.IsValueType) return ""; StringBuilder sb = new StringBuilder(); if (type.IsPrimitive) { sb.AppendLine(string.Format(" static {0} GetInstance(ILRuntime.Runtime.Enviorment.AppDomain __domain, StackObject* ptr_of_this_method, IList __mStack)", typeClsName)); sb.AppendLine(" {"); if (type.IsPrimitive || type.IsValueType) sb.AppendLine(" ptr_of_this_method = ILIntepreter.GetObjectAndResolveReference(ptr_of_this_method);"); sb.AppendLine(string.Format(" {0} instance_of_this_method;", typeClsName)); sb.Append(@" switch(ptr_of_this_method->ObjectType) { case ObjectTypes.FieldReference: { var instance_of_fieldReference = __mStack[ptr_of_this_method->Value]; if(instance_of_fieldReference is ILTypeInstance) { instance_of_this_method = ("); sb.Append(typeClsName); sb.Append(")"); if(type == typeof(bool)) { sb.Append("((int)"); } sb.Append("((ILTypeInstance)instance_of_fieldReference)[ptr_of_this_method->ValueLow]"); if (type == typeof(bool)) { sb.Append(" == 1);"); } else sb.Append(";"); sb.Append(@" } else { var t = __domain.GetType(instance_of_fieldReference.GetType()) as CLRType; instance_of_this_method = ("); sb.Append(typeClsName); sb.Append(")t.GetFieldValue(ptr_of_this_method->ValueLow, instance_of_fieldReference);"); sb.Append(@" } } break; case ObjectTypes.StaticFieldReference: { var t = __domain.GetType(ptr_of_this_method->Value); if(t is ILType) { instance_of_this_method = ("); sb.Append(typeClsName); sb.Append(")"); if (type == typeof(bool)) { sb.Append("((int)"); } sb.Append("((ILType)t).StaticInstance[ptr_of_this_method->ValueLow]"); if (type == typeof(bool)) { sb.Append(" == 1);"); } else sb.Append(";"); sb.Append(@" } else { instance_of_this_method = ("); sb.Append(typeClsName); sb.Append(@")((CLRType)t).GetFieldValue(ptr_of_this_method->ValueLow, null); } } break; case ObjectTypes.ArrayReference: { var instance_of_arrayReference = __mStack[ptr_of_this_method->Value] as "); sb.Append(typeClsName); sb.AppendLine(@"[]; instance_of_this_method = instance_of_arrayReference[ptr_of_this_method->ValueLow]; } break; default:"); sb.AppendLine(string.Format(" instance_of_this_method = {0};", type.GetRetrieveValueCode(typeClsName))); sb.AppendLine(@" break; } return instance_of_this_method;"); sb.AppendLine(" }"); } if (!type.IsPrimitive && !type.IsAbstract) { sb.AppendLine(string.Format(" static void WriteBackInstance(ILRuntime.Runtime.Enviorment.AppDomain __domain, StackObject* ptr_of_this_method, IList __mStack, ref {0} instance_of_this_method)", typeClsName)); sb.AppendLine(" {"); sb.AppendLine(@" ptr_of_this_method = ILIntepreter.GetObjectAndResolveReference(ptr_of_this_method); switch(ptr_of_this_method->ObjectType) { case ObjectTypes.Object: { __mStack[ptr_of_this_method->Value] = instance_of_this_method;"); sb.Append(@" } break; case ObjectTypes.FieldReference: { var ___obj = __mStack[ptr_of_this_method->Value]; if(___obj is ILTypeInstance) { ((ILTypeInstance)___obj)[ptr_of_this_method->ValueLow] = instance_of_this_method"); sb.Append(@"; } else { var t = __domain.GetType(___obj.GetType()) as CLRType; t.SetFieldValue(ptr_of_this_method->ValueLow, ref ___obj, instance_of_this_method"); sb.Append(@"); } } break; case ObjectTypes.StaticFieldReference: { var t = __domain.GetType(ptr_of_this_method->Value); if(t is ILType) { ((ILType)t).StaticInstance[ptr_of_this_method->ValueLow] = instance_of_this_method"); sb.Append(@"; } else { ((CLRType)t).SetStaticFieldValue(ptr_of_this_method->ValueLow, instance_of_this_method"); sb.Append(@"); } } break; case ObjectTypes.ArrayReference: { var instance_of_arrayReference = __mStack[ptr_of_this_method->Value] as "); sb.Append(typeClsName); sb.AppendLine(@"[]; instance_of_arrayReference[ptr_of_this_method->ValueLow] = instance_of_this_method; } break; }"); sb.AppendLine(@" }"); } return sb.ToString(); } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/CLRBinding/ConstructorBindingGenerator.cs ================================================ using System; using System.Collections.Generic; using System.Reflection; using System.Linq; using System.Text; using ILRuntime.Runtime.Enviorment; namespace ILRuntime.Runtime.CLRBinding { static class ConstructorBindingGenerator { internal static string GenerateConstructorRegisterCode(this Type type, ConstructorInfo[] methods, HashSet excludes) { StringBuilder sb = new StringBuilder(); int idx = 0; foreach (var i in methods) { if (excludes != null && excludes.Contains(i)) continue; if (type.ShouldSkipMethod(i)) continue; var param = i.GetParameters(); StringBuilder sb2 = new StringBuilder(); sb2.Append("{"); bool first = true; foreach (var j in param) { if (first) first = false; else sb2.Append(", "); sb2.Append("typeof("); string tmp, clsName; bool isByRef; j.ParameterType.GetClassName(out tmp, out clsName, out isByRef); sb2.Append(clsName); sb2.Append(")"); if (isByRef) sb2.Append(".MakeByRefType()"); } sb2.Append("}"); sb.AppendLine(string.Format(" args = new Type[]{0};", sb2)); sb.AppendLine(" method = type.GetConstructor(flag, null, args, null);"); sb.AppendLine(string.Format(" app.RegisterCLRMethodRedirection(method, Ctor_{0});",idx)); idx++; } return sb.ToString(); } internal static string GenerateConstructorWraperCode(this Type type, ConstructorInfo[] methods, string typeClsName, HashSet excludes) { StringBuilder sb = new StringBuilder(); int idx = 0; foreach (var i in methods) { if (excludes != null && excludes.Contains(i)) continue; if (type.ShouldSkipMethod(i) || i.IsStatic) continue; var param = i.GetParameters(); int paramCnt = param.Length; sb.AppendLine(string.Format(" static StackObject* Ctor_{0}(ILIntepreter __intp, StackObject* __esp, IList __mStack, CLRMethod __method, bool isNewObj)", idx)); sb.AppendLine(" {"); sb.AppendLine(" ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain;"); sb.AppendLine(" StackObject* ptr_of_this_method;"); sb.AppendLine(string.Format(" StackObject* __ret = ILIntepreter.Minus(__esp, {0});", paramCnt)); for (int j = param.Length; j > 0; j--) { var p = param[j - 1]; sb.AppendLine(string.Format(" ptr_of_this_method = ILIntepreter.Minus(__esp, {0});", param.Length - j + 1)); string tmp, clsName; bool isByRef; p.ParameterType.GetClassName(out tmp, out clsName, out isByRef); if (isByRef) sb.AppendLine(" ptr_of_this_method = ILIntepreter.GetObjectAndResolveReference(ptr_of_this_method);"); sb.AppendLine(string.Format(" {0} {1} = {2};", clsName, p.Name, p.ParameterType.GetRetrieveValueCode(clsName))); if (!isByRef && !p.ParameterType.IsPrimitive) sb.AppendLine(" __intp.Free(ptr_of_this_method);"); } sb.AppendLine(); sb.Append(" var result_of_this_method = "); { string tmp, clsName; bool isByRef; type.GetClassName(out tmp, out clsName, out isByRef); sb.Append(string.Format("new {0}(", clsName)); param.AppendParameters(sb); sb.AppendLine(");"); } sb.AppendLine(); if (type.IsValueType) { sb.AppendLine(@" if(!isNewObj) { __ret--; WriteBackInstance(__domain, __ret, __mStack, ref result_of_this_method); return __ret; }"); } //Ref/Out for (int j = param.Length; j > 0; j--) { var p = param[j - 1]; if (!p.ParameterType.IsByRef) continue; string tmp, clsName; bool isByRef; p.ParameterType.GetElementType().GetClassName(out tmp, out clsName, out isByRef); sb.AppendLine(string.Format(" ptr_of_this_method = ILIntepreter.Minus(__esp, {0});", param.Length - j + 1)); sb.AppendLine(@" switch(ptr_of_this_method->ObjectType) { case ObjectTypes.StackObjectReference: { var ___dst = *(StackObject**)&ptr_of_this_method->Value;"); p.ParameterType.GetElementType().GetRefWriteBackValueCode(sb, p.Name); sb.Append(@" } break; case ObjectTypes.FieldReference: { var ___obj = __mStack[ptr_of_this_method->Value]; if(___obj is ILTypeInstance) { ((ILTypeInstance)___obj)[ptr_of_this_method->ValueLow] = "); sb.Append(p.Name); sb.Append(@"; } else { var t = __domain.GetType(___obj.GetType()) as CLRType; t.SetFieldValue(ptr_of_this_method->ValueLow, ref ___obj, "); sb.Append(p.Name); sb.Append(@"); } } break; case ObjectTypes.StaticFieldReference: { var t = __domain.GetType(ptr_of_this_method->Value); if(t is ILType) { ((ILType)t).StaticInstance[ptr_of_this_method->ValueLow] = "); sb.Append(p.Name); sb.Append(@"; } else { ((CLRType)t).SetStaticFieldValue(ptr_of_this_method->ValueLow, "); sb.Append(p.Name); sb.Append(@"); } } break; case ObjectTypes.ArrayReference: { var instance_of_arrayReference = __mStack[ptr_of_this_method->Value] as "); sb.Append(clsName); sb.Append(@"[]; instance_of_arrayReference[ptr_of_this_method->ValueLow] = "); sb.Append(p.Name); sb.AppendLine(@"; } break; }"); sb.AppendLine(); } sb.AppendLine(" return ILIntepreter.PushObject(__ret, __mStack, result_of_this_method);"); sb.AppendLine(" }"); sb.AppendLine(); idx++; } return sb.ToString(); } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/CLRBinding/FieldBindingGenerator.cs ================================================ using System; using System.Collections.Generic; using System.Reflection; using System.Linq; using System.Text; using ILRuntime.Runtime.Enviorment; namespace ILRuntime.Runtime.CLRBinding { static class FieldBindingGenerator { internal static string GenerateFieldRegisterCode(this Type type, FieldInfo[] fields, HashSet excludes) { StringBuilder sb = new StringBuilder(); int idx = 0; foreach (var i in fields) { if (excludes != null && excludes.Contains(i)) continue; if (type.ShouldSkipField(i)) continue; if (i.IsSpecialName) continue; sb.AppendLine(string.Format(" field = type.GetField(\"{0}\", flag);", i.Name)); sb.AppendLine(string.Format(" app.RegisterCLRFieldGetter(field, get_{0}_{1});", i.Name, idx)); if (!i.IsInitOnly && !i.IsLiteral) { sb.AppendLine(string.Format(" app.RegisterCLRFieldSetter(field, set_{0}_{1});", i.Name, idx)); } idx++; } return sb.ToString(); } internal static string GenerateFieldWraperCode(this Type type, FieldInfo[] fields, string typeClsName, HashSet excludes) { StringBuilder sb = new StringBuilder(); int idx = 0; foreach (var i in fields) { if (excludes != null && excludes.Contains(i)) continue; if (type.ShouldSkipField(i)) continue; sb.AppendLine(string.Format(" static object get_{0}_{1}(ref object o)", i.Name, idx)); sb.AppendLine(" {"); if (i.IsStatic) { sb.AppendLine(string.Format(" return {0}.{1};", typeClsName, i.Name)); } else { sb.AppendLine(string.Format(" return (({0})o).{1};", typeClsName, i.Name)); } sb.AppendLine(" }"); if (!i.IsInitOnly && !i.IsLiteral) { sb.AppendLine(string.Format(" static void set_{0}_{1}(ref object o, object v)", i.Name, idx)); sb.AppendLine(" {"); string clsName, realClsName; bool isByRef; i.FieldType.GetClassName(out clsName, out realClsName, out isByRef); if (i.IsStatic) { sb.AppendLine(string.Format(" {0}.{1} = ({2})v;", typeClsName, i.Name, realClsName)); } else { if (CheckCanPinn(type)) { sb.AppendLine(" var h = GCHandle.Alloc(o, GCHandleType.Pinned);"); sb.AppendLine(string.Format(" {0}* p = ({0} *)(void *)h.AddrOfPinnedObject();", typeClsName)); sb.AppendLine(string.Format(" p->{0} = ({1})v;", i.Name, realClsName)); sb.AppendLine(" h.Free();"); } else { sb.AppendLine(string.Format(" (({0})o).{1} = ({2})v;", typeClsName, i.Name, realClsName)); } } sb.AppendLine(" }"); } idx++; } return sb.ToString(); } internal static bool CheckCanPinn(this Type type) { if (type.IsValueType) { FieldInfo[] fi = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); bool res = true; foreach(var i in fi) { if(!i.FieldType.IsPrimitive) { res = false; break; } } return res; } else return false; } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/CLRBinding/MethodBindingGenerator.cs ================================================ using System; using System.Collections.Generic; using System.Reflection; using System.Linq; using System.Text; using ILRuntime.Runtime.Enviorment; namespace ILRuntime.Runtime.CLRBinding { static class MethodBindingGenerator { internal static string GenerateMethodRegisterCode(this Type type, MethodInfo[] methods, HashSet excludes) { StringBuilder sb = new StringBuilder(); int idx = 0; foreach (var i in methods) { if (excludes != null && excludes.Contains(i)) continue; if (type.ShouldSkipMethod(i)) continue; bool isProperty = i.IsSpecialName; var param = i.GetParameters(); StringBuilder sb2 = new StringBuilder(); sb2.Append("{"); bool first = true; foreach (var j in param) { if (first) first = false; else sb2.Append(", "); sb2.Append("typeof("); string tmp, clsName; bool isByRef; j.ParameterType.GetClassName(out tmp, out clsName, out isByRef); sb2.Append(clsName); sb2.Append(")"); if (isByRef) sb2.Append(".MakeByRefType()"); } sb2.Append("}"); sb.AppendLine(string.Format(" args = new Type[]{0};", sb2)); sb.AppendLine(string.Format(" method = type.GetMethod(\"{0}\", flag, null, args, null);", i.Name)); sb.AppendLine(string.Format(" app.RegisterCLRMethodRedirection(method, {0}_{1});", i.Name, idx)); idx++; } return sb.ToString(); } internal static string GenerateMethodWraperCode(this Type type, MethodInfo[] methods, string typeClsName, HashSet excludes) { StringBuilder sb = new StringBuilder(); int idx = 0; foreach (var i in methods) { if (excludes != null && excludes.Contains(i)) continue; if (type.ShouldSkipMethod(i)) continue; bool isProperty = i.IsSpecialName; var param = i.GetParameters(); int paramCnt = param.Length; if (!i.IsStatic) paramCnt++; sb.AppendLine(string.Format(" static StackObject* {0}_{1}(ILIntepreter __intp, StackObject* __esp, IList __mStack, CLRMethod __method, bool isNewObj)", i.Name, idx)); sb.AppendLine(" {"); sb.AppendLine(" ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain;"); sb.AppendLine(" StackObject* ptr_of_this_method;"); sb.AppendLine(string.Format(" StackObject* __ret = ILIntepreter.Minus(__esp, {0});", paramCnt)); for (int j = param.Length; j > 0; j--) { var p = param[j - 1]; sb.AppendLine(string.Format(" ptr_of_this_method = ILIntepreter.Minus(__esp, {0});", param.Length - j + 1)); string tmp, clsName; bool isByRef; p.ParameterType.GetClassName(out tmp, out clsName, out isByRef); if (isByRef) sb.AppendLine(" ptr_of_this_method = ILIntepreter.GetObjectAndResolveReference(ptr_of_this_method);"); sb.AppendLine(string.Format(" {0} {1} = {2};", clsName, p.Name, p.ParameterType.GetRetrieveValueCode(clsName))); if (!isByRef && !p.ParameterType.IsPrimitive) sb.AppendLine(" __intp.Free(ptr_of_this_method);"); } if (!i.IsStatic) { sb.AppendLine(string.Format(" ptr_of_this_method = ILIntepreter.Minus(__esp, {0});", paramCnt)); if (type.IsPrimitive) sb.AppendLine(string.Format(" {0} instance_of_this_method = GetInstance(__domain, ptr_of_this_method, __mStack);", typeClsName)); else { if (type.IsValueType) sb.AppendLine(" ptr_of_this_method = ILIntepreter.GetObjectAndResolveReference(ptr_of_this_method);"); sb.AppendLine(string.Format(" {0} instance_of_this_method;", typeClsName)); sb.AppendLine(string.Format(" instance_of_this_method = {0};", type.GetRetrieveValueCode(typeClsName))); if (!type.IsValueType) sb.AppendLine(" __intp.Free(ptr_of_this_method);"); } } sb.AppendLine(); if (i.ReturnType != typeof(void)) { sb.Append(" var result_of_this_method = "); } else sb.Append(" "); if (i.IsStatic) { if (isProperty) { string[] t = i.Name.Split('_'); string propType = t[0]; if (propType == "get") { bool isIndexer = param.Length > 0; if (isIndexer) { sb.AppendLine(string.Format("{1}[{0}];", param[0].Name, typeClsName)); } else sb.AppendLine(string.Format("{1}.{0};", t[1], typeClsName)); } else if (propType == "set") { bool isIndexer = param.Length > 1; if (isIndexer) { sb.AppendLine(string.Format("{2}[{0}] = {1};", param[0].Name, param[1].Name, typeClsName)); } else sb.AppendLine(string.Format("{2}.{0} = {1};", t[1], param[0].Name, typeClsName)); } else if (propType == "op") { switch (t[1]) { case "Equality": sb.AppendLine(string.Format("{0} == {1};", param[0].Name, param[1].Name)); break; case "Inequality": sb.AppendLine(string.Format("{0} != {1};", param[0].Name, param[1].Name)); break; case "Addition": sb.AppendLine(string.Format("{0} + {1};", param[0].Name, param[1].Name)); break; case "Subtraction": sb.AppendLine(string.Format("{0} - {1};", param[0].Name, param[1].Name)); break; case "Multiply": sb.AppendLine(string.Format("{0} * {1};", param[0].Name, param[1].Name)); break; case "Division": sb.AppendLine(string.Format("{0} / {1};", param[0].Name, param[1].Name)); break; case "GreaterThan": sb.AppendLine(string.Format("{0} > {1};", param[0].Name, param[1].Name)); break; case "GreaterThanOrEqual": sb.AppendLine(string.Format("{0} >= {1};", param[0].Name, param[1].Name)); break; case "LessThan": sb.AppendLine(string.Format("{0} < {1};", param[0].Name, param[1].Name)); break; case "LessThanOrEqual": sb.AppendLine(string.Format("{0} <= {1};", param[0].Name, param[1].Name)); break; case "UnaryNegation": sb.AppendLine(string.Format("-{0};", param[0].Name)); break; case "Implicit": case "Explicit": { string tmp, clsName; bool isByRef; i.ReturnType.GetClassName(out tmp, out clsName, out isByRef); sb.AppendLine(string.Format("({1}){0};", param[0].Name, clsName)); } break; default: throw new NotImplementedException(i.Name); } } else throw new NotImplementedException(); } else { sb.Append(string.Format("{0}.{1}(", typeClsName, i.Name)); param.AppendParameters(sb); sb.AppendLine(");"); } } else { if (isProperty) { string[] t = i.Name.Split('_'); string propType = t[0]; if (propType == "get") { bool isIndexer = param.Length > 0; if (isIndexer) { sb.AppendLine(string.Format("instance_of_this_method[{0}];", param[0].Name)); } else sb.AppendLine(string.Format("instance_of_this_method.{0};", t[1])); } else if (propType == "set") { bool isIndexer = param.Length > 1; if (isIndexer) { sb.AppendLine(string.Format("instance_of_this_method[{0}] = {1};", param[0].Name, param[1].Name)); } else sb.AppendLine(string.Format("instance_of_this_method.{0} = {1};", t[1], param[0].Name)); } else throw new NotImplementedException(); } else { sb.Append(string.Format("instance_of_this_method.{0}(", i.Name)); param.AppendParameters(sb); sb.AppendLine(");"); } } sb.AppendLine(); if (!i.IsStatic && type.IsValueType && !type.IsPrimitive)//need to write back value type instance { sb.AppendLine(" WriteBackInstance(__domain, ptr_of_this_method, __mStack, ref instance_of_this_method);"); sb.AppendLine(); } //Ref/Out for (int j = param.Length; j > 0; j--) { var p = param[j - 1]; if (!p.ParameterType.IsByRef) continue; string tmp, clsName; bool isByRef; p.ParameterType.GetElementType().GetClassName(out tmp, out clsName, out isByRef); sb.AppendLine(string.Format(" ptr_of_this_method = ILIntepreter.Minus(__esp, {0});", param.Length - j + 1)); sb.AppendLine(@" switch(ptr_of_this_method->ObjectType) { case ObjectTypes.StackObjectReference: { var ___dst = *(StackObject**)&ptr_of_this_method->Value;"); p.ParameterType.GetElementType().GetRefWriteBackValueCode(sb, p.Name); sb.Append(@" } break; case ObjectTypes.FieldReference: { var ___obj = __mStack[ptr_of_this_method->Value]; if(___obj is ILTypeInstance) { ((ILTypeInstance)___obj)[ptr_of_this_method->ValueLow] = "); sb.Append(p.Name); sb.Append(@"; } else { var t = __domain.GetType(___obj.GetType()) as CLRType; t.SetFieldValue(ptr_of_this_method->ValueLow, ref ___obj, "); sb.Append(p.Name); sb.Append(@"); } } break; case ObjectTypes.StaticFieldReference: { var t = __domain.GetType(ptr_of_this_method->Value); if(t is ILType) { ((ILType)t).StaticInstance[ptr_of_this_method->ValueLow] = "); sb.Append(p.Name); sb.Append(@"; } else { ((CLRType)t).SetStaticFieldValue(ptr_of_this_method->ValueLow, "); sb.Append(p.Name); sb.Append(@"); } } break; case ObjectTypes.ArrayReference: { var instance_of_arrayReference = __mStack[ptr_of_this_method->Value] as "); sb.Append(clsName); sb.Append(@"[]; instance_of_arrayReference[ptr_of_this_method->ValueLow] = "); sb.Append(p.Name); sb.AppendLine(@"; } break; }"); sb.AppendLine(); } if (i.ReturnType != typeof(void)) { i.ReturnType.GetReturnValueCode(sb); } else sb.AppendLine(" return __ret;"); sb.AppendLine(" }"); sb.AppendLine(); idx++; } return sb.ToString(); } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/CLRBinding/ValueTypeBindingGenerator.cs ================================================ using System; using System.Collections.Generic; using System.Reflection; using System.Linq; using System.Text; using ILRuntime.Runtime.Enviorment; namespace ILRuntime.Runtime.CLRBinding { static class ValueTypeBindingGenerator { internal static string GenerateValueTypeRegisterCode(this Type type, string typeClsName) { StringBuilder sb = new StringBuilder(); if (type.IsValueType && !type.IsPrimitive && !type.IsEnum) { sb.AppendLine(" app.RegisterCLRMemberwiseClone(type, PerformMemberwiseClone);"); } return sb.ToString(); } internal static string GenerateCloneWraperCode(this Type type, FieldInfo[] fields, string typeClsName) { if (!type.IsValueType || type.IsPrimitive) return string.Empty; StringBuilder sb = new StringBuilder(); sb.AppendLine(" static object PerformMemberwiseClone(ref object o)"); sb.AppendLine(" {"); sb.AppendLine(string.Format(" return new {0}", typeClsName)); sb.AppendLine(" {"); foreach (var i in fields) { if (i.IsStatic || i.IsInitOnly || i.IsLiteral) continue; sb.AppendLine(string.Format(" {0} = (({1}) o).{0},", i.Name, typeClsName)); } sb.AppendLine(" };"); sb.AppendLine(" }"); return sb.ToString(); } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/BreakPointContext.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Stack; namespace ILRuntime.Runtime.Debugger { unsafe class BreakPointContext { public ILIntepreter Interpreter { get; set; } public Exception Exception { get; set; } public string DumpContext() { /*StringBuilder sb = new StringBuilder(); if (Exception != null) sb.AppendLine(Exception.Message); StackFrame[] frames = Interpreter.Stack.Frames.ToArray(); StackFrame topFrame = frames[0]; var m = topFrame.Method; if (m.HasThis) { sb.AppendLine("this:"); sb.AppendLine(DebugService.Instance.GetThisInfo(Interpreter)); } sb.AppendLine("->" + topFrame.Method.Definition.Body.Instructions[topFrame.Address.Value]); sb.AppendLine("Local Variables:"); sb.AppendLine(DebugService.Instance.GetLocalVariableInfo(Interpreter)); sb.Append(DebugService.Instance.GetStackTrance(Interpreter)); return sb.ToString();*/ return null; } string GetStackObjectValue(StackObject val, IList mStack) { string v; switch (val.ObjectType) { case ObjectTypes.Null: v = "null"; break; case ObjectTypes.Integer: v = val.Value.ToString(); break; case ObjectTypes.Object: { object obj = Interpreter.Stack.ManagedStack[val.Value]; v = obj.ToString(); } break; default: v = "Unknown type"; break; } return v; } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/BreakpointInfo.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger { class BreakpointInfo { public int BreakpointHashCode { get; set; } public int MethodHashCode { get; set; } public int StartLine { get; set; } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/DebugMessageType.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger { public enum DebugMessageType { CSAttach, SCAttachResult, CSBindBreakpoint, SCBindBreakpointResult, SCModuleLoaded, SCThreadStarted, SCThreadEnded, SCBreakpointHit, CSDeleteBreakpoint, CSExecute, CSStep, SCStepComplete, CSResolveVariable, SCResolveVariableResult } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/DebugService.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Stack; using ILRuntime.CLR.Utils; namespace ILRuntime.Runtime.Debugger { public class DebugService { BreakPointContext curBreakpoint; DebuggerServer server; Runtime.Enviorment.AppDomain domain; Dictionary> activeBreakpoints = new Dictionary>(); Dictionary breakpointMapping = new Dictionary(); AutoResetEvent evt = new AutoResetEvent(false); public Action OnBreakPoint; public Enviorment.AppDomain AppDomain { get { return domain; } } public AutoResetEvent BlockEvent { get { return evt; } } public bool IsDebuggerAttached { get { #if DEBUG return (server != null && server.IsAttached); #else return false; #endif } } public DebugService(Runtime.Enviorment.AppDomain domain) { this.domain = domain; } /// /// Start Debugger Server /// /// Port to listen on public void StartDebugService(int port) { #if DEBUG server = new Debugger.DebuggerServer(this); server.Port = port; server.Start(); #endif } /// /// Stop Debugger Server /// public void StopDebugService() { #if DEBUG server.Stop(); server = null; #endif } /// /// 中断运行 /// /// /// /// 如果挂的有调试器则返回true internal bool Break(ILIntepreter intpreter, Exception ex = null) { BreakPointContext ctx = new BreakPointContext(); ctx.Interpreter = intpreter; ctx.Exception = ex; curBreakpoint = ctx; if (OnBreakPoint != null) { OnBreakPoint(ctx.DumpContext()); return true; } return false; } public string GetStackTrance(ILIntepreter intepreper) { StringBuilder sb = new StringBuilder(); ILRuntime.CLR.Method.ILMethod m; StackFrame[] frames = intepreper.Stack.Frames.ToArray(); Mono.Cecil.Cil.Instruction ins = null; if (frames[0].Address != null) { ins = frames[0].Method.Definition.Body.Instructions[frames[0].Address.Value]; sb.AppendLine(ins.ToString()); } for (int i = 0; i < frames.Length; i++) { var f = frames[i]; m = f.Method; string document = ""; if (f.Address != null) { ins = m.Definition.Body.Instructions[f.Address.Value]; var seq = FindSequencePoint(ins); if (seq != null) { document = string.Format("{0}:Line {1}", seq.Document.Url, seq.StartLine); } } sb.AppendFormat("at {0} {1}\r\n", m, document); } return sb.ToString(); } public unsafe string GetThisInfo(ILIntepreter intepreter) { var topFrame = intepreter.Stack.Frames.Peek(); var arg = Minus(topFrame.LocalVarPointer, topFrame.Method.ParameterCount); if (topFrame.Method.HasThis) arg--; if (arg->ObjectType == ObjectTypes.StackObjectReference) { arg = *(StackObject**)&arg->Value; } ILTypeInstance instance = arg->ObjectType != ObjectTypes.Null ? intepreter.Stack.ManagedStack[arg->Value] as ILTypeInstance : null; if (instance == null) return "null"; var fields = instance.Type.TypeDefinition.Fields; int idx = 0; StringBuilder sb = new StringBuilder(); for (int i = 0; i < fields.Count; i++) { var f = fields[i]; if (f.IsStatic) continue; var field = instance.Fields[idx]; var v = StackObject.ToObject(&field, intepreter.AppDomain, instance.ManagedObjects); if (v == null) v = "null"; string name = f.Name; sb.AppendFormat("{0} {1} = {2}", f.FieldType.Name, name, v); if ((idx % 3 == 0 && idx != 0) || idx == instance.Fields.Length - 1) sb.AppendLine(); else sb.Append(", "); idx++; } return sb.ToString(); } public unsafe string GetLocalVariableInfo(ILIntepreter intepreter) { StackFrame topFrame = intepreter.Stack.Frames.Peek(); var m = topFrame.Method; StringBuilder sb = new StringBuilder(); for (int i = 0; i < m.LocalVariableCount; i++) { var lv = m.Definition.Body.Variables[i]; var val = Add(topFrame.LocalVarPointer, i); var v = StackObject.ToObject(val, intepreter.AppDomain, intepreter.Stack.ManagedStack); if (v == null) v = "null"; string name = string.IsNullOrEmpty(lv.Name) ? "v" + lv.Index : lv.Name; sb.AppendFormat("{0} {1} = {2}", lv.VariableType.Name, name, v); if ((i % 3 == 0 && i != 0) || i == m.LocalVariableCount - 1) sb.AppendLine(); else sb.Append(", "); } return sb.ToString(); } internal static Mono.Cecil.Cil.SequencePoint FindSequencePoint(Mono.Cecil.Cil.Instruction ins) { Mono.Cecil.Cil.Instruction cur = ins; while (cur.SequencePoint == null && cur.Previous != null) cur = cur.Previous; return cur.SequencePoint; } unsafe StackObject* Add(StackObject* a, int b) { return (StackObject*)((long)a + sizeof(StackObject) * b); } unsafe StackObject* Minus(StackObject* a, int b) { return (StackObject*)((long)a - sizeof(StackObject) * b); } internal void NotifyModuleLoaded(string moduleName) { if (server != null && server.IsAttached) server.NotifyModuleLoaded(moduleName); } internal void SetBreakPoint(int methodHash, int bpHash, int startLine) { lock (activeBreakpoints) { LinkedList lst; if(!activeBreakpoints.TryGetValue(methodHash, out lst)) { lst = new LinkedList(); activeBreakpoints[methodHash] = lst; } BreakpointInfo bpInfo = new BreakpointInfo(); bpInfo.BreakpointHashCode = bpHash; bpInfo.MethodHashCode = methodHash; bpInfo.StartLine = startLine; lst.AddLast(bpInfo); breakpointMapping[bpHash] = bpInfo; } } internal void DeleteBreakpoint(int bpHash) { lock (activeBreakpoints) { BreakpointInfo bpInfo; if (breakpointMapping.TryGetValue(bpHash, out bpInfo)) { LinkedList lst; if(activeBreakpoints.TryGetValue(bpInfo.MethodHashCode, out lst)) { lst.Remove(bpInfo); } breakpointMapping.Remove(bpHash); } } } internal void ExecuteThread(int threadHash) { lock (AppDomain.FreeIntepreters) { foreach(var i in AppDomain.Intepreters) { //We should resume all threads on execute i.Value.ClearDebugState(); i.Value.Resume(); } } } internal unsafe void StepThread(int threadHash, StepTypes type) { lock (AppDomain.FreeIntepreters) { ILIntepreter intp; if(AppDomain.Intepreters.TryGetValue(threadHash, out intp)) { intp.ClearDebugState(); intp.CurrentStepType = type; intp.LastStepFrameBase = intp.Stack.Frames.Count > 0 ? intp.Stack.Frames.Peek().BasePointer : (StackObject*)0; intp.LastStepInstructionIndex = intp.Stack.Frames.Count > 0 ? intp.Stack.Frames.Peek().Address.Value : 0; intp.Resume(); } } } unsafe internal void CheckShouldBreak(ILMethod method, ILIntepreter intp, int ip) { if (server != null && server.IsAttached) { int methodHash = method.GetHashCode(); lock (activeBreakpoints) { LinkedList lst; bool bpHit = false; if (activeBreakpoints.TryGetValue(methodHash, out lst)) { var sp = method.Definition.Body.Instructions[ip].SequencePoint; if (sp != null) { foreach (var i in lst) { if ((i.StartLine + 1) == sp.StartLine) { DoBreak(intp, i.BreakpointHashCode, false); bpHit = true; break; } } } } if (!bpHit) { var sp = method.Definition.Body.Instructions[ip].SequencePoint; if (sp != null && IsSequenceValid(sp)) { switch (intp.CurrentStepType) { case StepTypes.Into: DoBreak(intp, 0, true); break; case StepTypes.Over: if (intp.Stack.Frames.Peek().BasePointer <= intp.LastStepFrameBase && ip != intp.LastStepInstructionIndex) { DoBreak(intp, 0, true); } break; case StepTypes.Out: { if (intp.Stack.Frames.Count > 0 && intp.Stack.Frames.Peek().BasePointer < intp.LastStepFrameBase) { DoBreak(intp, 0, true); } } break; } } } } } } bool IsSequenceValid(Mono.Cecil.Cil.SequencePoint sp) { return sp.StartLine != sp.EndLine || sp.StartColumn != sp.EndColumn; } void DoBreak(ILIntepreter intp, int bpHash, bool isStep) { KeyValuePair[] frames = new KeyValuePair[AppDomain.Intepreters.Count]; frames[0] = new KeyValuePair(intp.GetHashCode(), GetStackFrameInfo(intp)); int idx = 1; foreach (var j in AppDomain.Intepreters) { if (j.Value != intp) { j.Value.ShouldBreak = true; frames[idx++] = new KeyValuePair(j.Value.GetHashCode(), GetStackFrameInfo(j.Value)); } } if (!isStep) server.SendSCBreakpointHit(intp.GetHashCode(), bpHash, frames); else server.SendSCStepComplete(intp.GetHashCode(), frames); //Breakpoint hit intp.Break(); } unsafe StackFrameInfo[] GetStackFrameInfo(ILIntepreter intp) { StackFrame[] frames = intp.Stack.Frames.ToArray(); Mono.Cecil.Cil.Instruction ins = null; ILMethod m; StackFrameInfo[] frameInfos = new StackFrameInfo[frames.Length]; for (int j = 0; j < frames.Length; j++) { StackFrameInfo info = new Debugger.StackFrameInfo(); var f = frames[j]; m = f.Method; info.MethodName = m.ToString(); if (f.Address != null) { ins = m.Definition.Body.Instructions[f.Address.Value]; var seq = FindSequencePoint(ins); if (seq != null) { info.DocumentName = seq.Document.Url; info.StartLine = seq.StartLine - 1; info.StartColumn = seq.StartColumn - 1; info.EndLine = seq.EndLine - 1; info.EndColumn = seq.EndColumn - 1; } } StackFrame topFrame = f; m = topFrame.Method; int argumentCount = m.ParameterCount; if (m.HasThis) argumentCount++; info.LocalVariables = new VariableInfo[argumentCount + m.LocalVariableCount]; for(int i = 0; i < argumentCount; i++) { int argIdx = m.HasThis ? i - 1 : i; var arg = Minus(topFrame.LocalVarPointer, argumentCount); string name = null; object v = null; string typeName = null; var val = Add(arg, i); v = StackObject.ToObject(val, intp.AppDomain, intp.Stack.ManagedStack); if (v == null) v = "null"; if (argIdx >= 0) { var lv = m.Definition.Parameters[argIdx]; name = string.IsNullOrEmpty(lv.Name) ? "arg" + lv.Index : lv.Name; typeName = lv.ParameterType.FullName; if (v != null) v = m.Parameters[argIdx].TypeForCLR.CheckCLRTypes(v); } else { name = "this"; typeName = m.DeclearingType.FullName; } VariableInfo vinfo = new Debugger.VariableInfo(); vinfo.Address = (long)val; vinfo.Name = name; vinfo.Value = v.ToString(); vinfo.TypeName = typeName; vinfo.Expandable = GetValueExpandable(val, intp.Stack.ManagedStack); info.LocalVariables[i] = vinfo; } for (int i = argumentCount; i < info.LocalVariables.Length; i++) { var locIdx = i - argumentCount; var lv = m.Definition.Body.Variables[locIdx]; var val = Add(topFrame.LocalVarPointer, locIdx); var v = StackObject.ToObject(val, intp.AppDomain, intp.Stack.ManagedStack); if (v == null) v = "null"; else v = intp.AppDomain.GetType(lv.VariableType, m.DeclearingType, m).TypeForCLR.CheckCLRTypes(v); string name = string.IsNullOrEmpty(lv.Name) ? "v" + lv.Index : lv.Name; VariableInfo vinfo = new Debugger.VariableInfo(); vinfo.Address = (long)val; vinfo.Name = name; vinfo.Value = v.ToString(); vinfo.TypeName = lv.VariableType.FullName; vinfo.Expandable = GetValueExpandable(val, intp.Stack.ManagedStack); info.LocalVariables[i] = vinfo; } frameInfos[j] = info; } return frameInfos; } internal VariableInfo ResolveVariable(VariableReference parent, string name) { return null; } unsafe bool GetValueExpandable(StackObject* esp, IList mStack) { if (esp->ObjectType < ObjectTypes.Object) return false; else { var obj = mStack[esp->Value]; if (obj == null) return false; if (obj is ILTypeInstance) return true; else if (obj.GetType().IsPrimitive) return false; else return true; } } internal void ThreadStarted(ILIntepreter intp) { if (server != null && server.IsAttached) { server.SendSCThreadStarted(intp.GetHashCode()); } } internal void ThreadEnded(ILIntepreter intp) { if (server != null && server.IsAttached) { server.SendSCThreadEnded(intp.GetHashCode()); } } internal void Detach() { activeBreakpoints.Clear(); breakpointMapping.Clear(); foreach (var j in AppDomain.Intepreters) { j.Value.ClearDebugState(); j.Value.Resume(); } } internal unsafe void DumpStack(StackObject* esp, RuntimeStack stack) { #if !UNITY_5 && !UNITY_2017 && !UNITY_4 var start = stack.StackBase; var end = esp + 10; var frames = stack.Frames; var mStack = stack.ManagedStack; var valuePointerEnd = stack.ValueTypeStackPointer; HashSet leakVObj = new HashSet(); for (var i = stack.ValueTypeStackBase; i > stack.ValueTypeStackPointer;) { leakVObj.Add((long)i); i = Minus(i, i->ValueLow + 1); } for (var i = start; i <= end; i++) { StringBuilder sb = new StringBuilder(); ILMethod localMethod = null, baseMethod = null; bool isLocal = false; bool isBase = false; int localIdx = 0; if (i == esp) sb.Append("->"); foreach (var j in frames) { if (i >= j.LocalVarPointer && i < j.BasePointer) { isLocal = true; localIdx = (int)(i - j.LocalVarPointer); localMethod = j.Method; } else if (i == j.BasePointer) { isBase = true; baseMethod = j.Method; } } sb.Append(string.Format("(0x{0:X8}) Type:{1} ", (long)i, i->ObjectType)); GetStackObjectText(sb, i, mStack, valuePointerEnd); if (i < esp) { if (i->ObjectType == ObjectTypes.ValueTypeObjectReference) VisitValueTypeReference(*(StackObject**)&i->Value, leakVObj); } if (isLocal) { sb.Append(string.Format("|Loc:{0}", localIdx)); if (localIdx == 0) { sb.Append(" Method:"); sb.Append(localMethod.ToString()); } } if (isBase) { sb.Append("|Base"); sb.Append(" Method:"); sb.Append(baseMethod.ToString()); } System.Diagnostics.Debug.Print(sb.ToString()); } for (var i = stack.ValueTypeStackBase; i > stack.ValueTypeStackPointer;) { var vt = domain.GetType(i->Value); var cnt = i->ValueLow; bool leak = leakVObj.Contains((long)i); System.Diagnostics.Debug.Print("----------------------------------------------"); System.Diagnostics.Debug.Print(string.Format("{2}(0x{0:X8}){1}", (long)i, vt, leak ? "*" : "")); for (int j = 0; j < cnt; j++) { StringBuilder sb = new StringBuilder(); var ptr = Minus(i, j + 1); sb.Append(string.Format("(0x{0:X8}) Type:{1} ", (long)ptr, ptr->ObjectType)); GetStackObjectText(sb, ptr, mStack, valuePointerEnd); System.Diagnostics.Debug.Print(sb.ToString()); } i = Minus(i, i->ValueLow + 1); } System.Diagnostics.Debug.Print("Managed Objects:"); for (int i = 0; i < mStack.Count; i++) { System.Diagnostics.Debug.Print(string.Format("({0}){1}", i, mStack[i])); } #endif } unsafe void GetStackObjectText(StringBuilder sb, StackObject* esp, IList mStack, StackObject* valueTypeEnd) { string text = "null"; switch (esp->ObjectType) { case ObjectTypes.StackObjectReference: { sb.Append(string.Format("Value:0x{0:X8}", (long)*(StackObject**)&esp->Value)); } break; case ObjectTypes.ValueTypeObjectReference: { object obj = null; var dst = *(StackObject**)&esp->Value; if (dst > valueTypeEnd) obj = StackObject.ToObject(esp, domain, mStack); if (obj != null) text = obj.ToString(); text += string.Format("({0})", domain.GetType(dst->Value)); } sb.Append(string.Format("Value:0x{0:X8} Text:{1} ", (long)*(StackObject**)&esp->Value, text)); break; default: { if (esp->ObjectType >= ObjectTypes.Null && esp->ObjectType <= ObjectTypes.ArrayReference) { if (esp->ObjectType < ObjectTypes.Object || esp->Value < mStack.Count) { var obj = StackObject.ToObject(esp, domain, mStack); if (obj != null) text = obj.ToString(); } } sb.Append(string.Format("Value:{0} ValueLow:{1} Text:{2} ", esp->Value, esp->ValueLow, text)); } break; } } unsafe void VisitValueTypeReference(StackObject* esp, HashSet leak) { leak.Remove((long)esp); for (int i = 0; i < esp->ValueLow; i++) { var ptr = Minus(esp, i + 1); if (ptr->ObjectType == ObjectTypes.ValueTypeObjectReference) { VisitValueTypeReference(*(StackObject**)&ptr->Value, leak); } } } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/DebugSocket.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Net.Sockets; namespace ILRuntime.Runtime.Debugger { public class DebugSocket { private Socket _socket = null; private bool _ready = false; bool connectFailed = false; private const int MAX_BUFF_SIZE = 256 * 1024; private const int HEAD_SIZE = 8; private byte[] _headBuffer = new byte[HEAD_SIZE]; private byte[] _sendBuffer = new byte[64 * 1024]; //private MemoryPoolSafe _packagePool = new MemoryPoolSafe(); //private Package _currPackage = null; private System.IO.MemoryStream _sendStream = null; BinaryWriter bw; const int RECV_BUFFER_SIZE = 1024; private MemoryStream recvBuffer = new MemoryStream(); private int lastMsgLength = -1; private byte[] socketAsyncBuffer = new byte[RECV_BUFFER_SIZE]; private SocketAsyncEventArgs saeArgs; private object socketLockObj = new object(); private byte[] _sendHeaderBuffer = new byte[HEAD_SIZE]; public bool Disconnected { get { return _socket == null || !_socket.Connected; } } public Action OnConnect { get; set; } public Action OnConnectFailed { get; set; } public Action OnClose { get; set; } public Action OnReciveMessage { get; set; } public DebugSocket() { _sendStream = new System.IO.MemoryStream(_sendBuffer); bw = new BinaryWriter(_sendStream); } public DebugSocket(Socket _socket) : this() { this._socket = _socket; BeginReceive(); _ready = true; } public void Connect(string ip, int port) { Close(); Socket socket; socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.BeginConnect(ip, port, new AsyncCallback(onConnected), this); _socket = socket; _ready = false; } private void AsyncRecv_Completed(object sender, SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success && e.BytesTransferred > 0) { try { ReceivePayload(e.Buffer, e.BytesTransferred); } catch (Exception ex) { Close(); return; } } else { Close(); return; } try { //继续接受数据 if (!_socket.ReceiveAsync(saeArgs)) { AsyncRecv_Completed(null, saeArgs); } } catch (Exception ex) { Close(); throw ex; } } private void ReceivePayload(byte[] data, int length) { if (_socket == null) return; if (!_socket.Connected) { Close(); return; } //接受数据并拼接成message byte[] msgBuff; //写入缓存 recvBuffer.Position = recvBuffer.Length; recvBuffer.Write(data, 0, length); //如果长度有错,返回 if (lastMsgLength < 0 && recvBuffer.Length < 4) { msgBuff = null; return; } recvBuffer.Position = 0; BinaryReader br = new BinaryReader(recvBuffer); //读取消息长度 if (lastMsgLength < 0) { lastMsgLength = br.ReadInt32() - 4; if (lastMsgLength > MAX_BUFF_SIZE) { Close(); throw new Exception("Too long package length!"); } } int remaining = (int)(recvBuffer.Length - recvBuffer.Position); //消息已经完整 while (remaining >= lastMsgLength && lastMsgLength > 0) { //读取一条消息 int type = br.ReadInt32(); msgBuff = br.ReadBytes(lastMsgLength - 4); if (OnReciveMessage != null) OnReciveMessage((DebugMessageType)type, msgBuff); lastMsgLength = -1; remaining = (int)(recvBuffer.Length - recvBuffer.Position); //保留剩余数据 if (remaining >= 4) { lastMsgLength = br.ReadInt32() - 4; remaining -= 4; if (lastMsgLength > MAX_BUFF_SIZE) { Close(); throw new Exception("Too long package length!"); } } } remaining = (int)(recvBuffer.Length - recvBuffer.Position); if (remaining > 0) { byte[] buffer = recvBuffer.GetBuffer(); Array.Copy(buffer, recvBuffer.Position, buffer, 0, remaining); } recvBuffer.Position = 0; recvBuffer.SetLength(remaining); } private void onConnected(IAsyncResult result) { if (_socket.Connected) { _socket.EndConnect(result); BeginReceive(); if (OnConnect != null) OnConnect(); //ReceiveOnce(); } else { if (OnConnectFailed != null) OnConnectFailed(); } } void BeginReceive() { saeArgs = new SocketAsyncEventArgs(); saeArgs.Completed += AsyncRecv_Completed; saeArgs.SetBuffer(socketAsyncBuffer, 0, socketAsyncBuffer.Length); _socket.ReceiveAsync(saeArgs); _ready = true; } //len type msg public void Send(DebugMessageType type, byte[] buffer, int len) { if (!_ready) return; //timeStamp = UnityEngine.Time.realtimeSinceStartup; _sendStream.Position = 0; bw.Write(len + HEAD_SIZE); bw.Write((int)type); bw.Write(buffer, 0, len); int totalLen = (int)_sendStream.Position; RawSend(_socket, _sendBuffer, totalLen); //_socket.Send(_sendBuffer, len, SocketFlags.None); } private void RawSend(Socket sock, byte[] buf, int end) { if (sock == null) return; if (end < 0) end = buf.Length; sock.Send(buf, end, SocketFlags.None); } public void Close() { if (_socket == null || !_ready) return; if (saeArgs != null) saeArgs.Dispose(); _socket.Close(); _socket = null; _ready = false; if (OnClose != null) { OnClose(); } } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/DebuggerServer/DebuggerServer.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Net.Sockets; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Debugger.Protocol; namespace ILRuntime.Runtime.Debugger { public class DebuggerServer { public const int Version = 1; TcpListener listener; //HashSet> clients = new HashSet>(); bool isUp = false; int maxNewConnections = 1; int port; Thread mainLoop; DebugSocket clientSocket; System.IO.MemoryStream sendStream = new System.IO.MemoryStream(64 * 1024); System.IO.BinaryWriter bw; DebugService ds; /// /// 服务器监听的端口 /// public int Port { get { return port; } set { this.port = value; } } public DebugSocket Client { get { return clientSocket; } } public bool IsAttached { get { return clientSocket != null && !clientSocket.Disconnected; } } public DebuggerServer(DebugService ds) { this.ds = ds; bw = new System.IO.BinaryWriter(sendStream); } public virtual bool Start() { mainLoop = new Thread(new ThreadStart(this.NetworkLoop)); mainLoop.Start(); this.listener = new TcpListener(port); try { listener.Start(); } catch { return false; } isUp = true; return true; } public virtual void Stop() { isUp = false; if (this.listener != null) this.listener.Stop(); mainLoop.Abort(); mainLoop = null; } void NetworkLoop() { while (true) { try { // let new clients (max 10) connect if (isUp && clientSocket == null) { for (int i = 0; listener.Pending() && i < maxNewConnections; i++) { CreateNewSession(listener); } } System.Threading.Thread.Sleep(1); } catch (ThreadAbortException) { } catch (Exception) { } } } void CreateNewSession(TcpListener listener) { Socket sock = listener.AcceptSocket(); clientSocket = new DebugSocket(sock); clientSocket.OnReciveMessage = OnReceive; clientSocket.OnClose = OnClose; ClientConnected(); } void ClientConnected() { } void OnClose() { ds.Detach(); clientSocket = null; } void OnReceive(DebugMessageType type, byte[] buffer) { if (clientSocket == null || clientSocket.Disconnected) return; System.IO.MemoryStream ms = new System.IO.MemoryStream(buffer); System.IO.BinaryReader br = new System.IO.BinaryReader(ms); switch (type) { case DebugMessageType.CSAttach: { SendAttachResult(); } break; case DebugMessageType.CSBindBreakpoint: { CSBindBreakpoint msg = new Protocol.CSBindBreakpoint(); msg.BreakpointHashCode = br.ReadInt32(); msg.TypeName = br.ReadString(); msg.MethodName = br.ReadString(); msg.StartLine = br.ReadInt32(); msg.EndLine = br.ReadInt32(); TryBindBreakpoint(msg); } break; case DebugMessageType.CSDeleteBreakpoint: { CSDeleteBreakpoint msg = new Protocol.CSDeleteBreakpoint(); msg.BreakpointHashCode = br.ReadInt32(); ds.DeleteBreakpoint(msg.BreakpointHashCode); } break; case DebugMessageType.CSExecute: { CSExecute msg = new Protocol.CSExecute(); msg.ThreadHashCode = br.ReadInt32(); ds.ExecuteThread(msg.ThreadHashCode); } break; case DebugMessageType.CSStep: { CSStep msg = new CSStep(); msg.ThreadHashCode = br.ReadInt32(); msg.StepType = (StepTypes)br.ReadByte(); ds.StepThread(msg.ThreadHashCode, msg.StepType); } break; case DebugMessageType.CSResolveVariable: { CSResolveVariable msg = new CSResolveVariable(); msg.Name = br.ReadString(); msg.Parent = ReadVariableReference(br); var info = ds.ResolveVariable(msg.Parent, msg.Name); } break; } } VariableReference ReadVariableReference(System.IO.BinaryReader br) { VariableReference res = null; if (br.ReadBoolean()) { res = new Debugger.VariableReference(); res.Address = br.ReadInt64(); res.Type = (VariableTypes)br.ReadByte(); res.Offset = br.ReadInt32(); res.Parent = ReadVariableReference(br); } return res; } void SendAttachResult() { sendStream.Position = 0; bw.Write((byte)AttachResults.OK); bw.Write(Version); DoSend(DebugMessageType.SCAttachResult); lock (ds.AppDomain.FreeIntepreters) { foreach (var i in ds.AppDomain.Intepreters) { SendSCThreadStarted(i.Key); } } } void DoSend(DebugMessageType type) { if (clientSocket != null && !clientSocket.Disconnected) clientSocket.Send(type, sendStream.GetBuffer(), (int)sendStream.Position); } void TryBindBreakpoint(CSBindBreakpoint msg) { var domain = ds.AppDomain; SCBindBreakpointResult res = new Protocol.SCBindBreakpointResult(); res.BreakpointHashCode = msg.BreakpointHashCode; IType type; if (domain.LoadedTypes.TryGetValue(msg.TypeName, out type)) { if(type is ILType) { ILType it = (ILType)type; ILMethod found = null; foreach(var i in it.GetMethods()) { if(i.Name == msg.MethodName) { ILMethod ilm = (ILMethod)i; if (ilm.StartLine <= (msg.StartLine + 1) && ilm.EndLine >= (msg.StartLine + 1)) { found = ilm; break; } } } if(found != null) { ds.SetBreakPoint(found.GetHashCode(), msg.BreakpointHashCode, msg.StartLine); res.Result = BindBreakpointResults.OK; } else { res.Result = BindBreakpointResults.CodeNotFound; } } else { res.Result = BindBreakpointResults.TypeNotFound; } } else { res.Result = BindBreakpointResults.TypeNotFound; } SendSCBindBreakpointResult(res); } void SendSCBindBreakpointResult(SCBindBreakpointResult msg) { sendStream.Position = 0; bw.Write(msg.BreakpointHashCode); bw.Write((byte)msg.Result); DoSend(DebugMessageType.SCBindBreakpointResult); } internal void SendSCBreakpointHit(int intpHash, int bpHash, KeyValuePair[] info) { sendStream.Position = 0; bw.Write(bpHash); bw.Write(intpHash); WriteStackFrames(info); DoSend(DebugMessageType.SCBreakpointHit); } internal void SendSCStepComplete(int intpHash, KeyValuePair[] info) { sendStream.Position = 0; bw.Write(intpHash); WriteStackFrames(info); DoSend(DebugMessageType.SCStepComplete); } void SendSCResolveVariableResult(VariableInfo info) { sendStream.Position = 0; WriteVariableInfo(info); DoSend(DebugMessageType.SCResolveVariableResult); } void WriteStackFrames(KeyValuePair[] info) { bw.Write(info.Length); foreach (var i in info) { bw.Write(i.Key); bw.Write(i.Value.Length); foreach (var j in i.Value) { bw.Write(j.MethodName); bw.Write(j.DocumentName); bw.Write(j.StartLine); bw.Write(j.StartColumn); bw.Write(j.EndLine); bw.Write(j.EndColumn); bw.Write(j.LocalVariables.Length); foreach (var k in j.LocalVariables) { WriteVariableInfo(k); } } } } void WriteVariableInfo(VariableInfo k) { bw.Write(k.Address); bw.Write((byte)k.Type); bw.Write(k.Offset); bw.Write(k.Name); bw.Write(k.Value); bw.Write(k.TypeName); bw.Write(k.Expandable); } internal void SendSCThreadStarted(int threadHash) { sendStream.Position = 0; bw.Write(threadHash); DoSend(DebugMessageType.SCThreadStarted); } internal void SendSCThreadEnded(int threadHash) { sendStream.Position = 0; bw.Write(threadHash); DoSend(DebugMessageType.SCThreadEnded); } public void NotifyModuleLoaded(string modulename) { sendStream.Position = 0; bw.Write(modulename); DoSend(DebugMessageType.SCModuleLoaded); } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/Protocol/CSBindBreakpoint.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class CSBindBreakpoint { public int BreakpointHashCode { get; set; } public string TypeName { get; set; } public string MethodName { get; set; } public int StartLine { get; set; } public int EndLine { get; set; } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/Protocol/CSDeleteBreakpoint.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class CSDeleteBreakpoint { public int BreakpointHashCode { get; set; } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/Protocol/CSExecute.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class CSExecute { public int ThreadHashCode { get; set; } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/Protocol/CSResolveVariable.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class CSResolveVariable { public string Name { get; set; } public VariableReference Parent { get; set; } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/Protocol/CSStep.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class CSStep { public int ThreadHashCode { get; set; } public StepTypes StepType { get; set; } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/Protocol/SCAttachResult.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public enum AttachResults { OK, AlreadyAttached, } public class SCAttachResult { public AttachResults Result { get; set; } public int DebugServerVersion { get; set; } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/Protocol/SCBindBreakpointResult.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public enum BindBreakpointResults { OK, TypeNotFound, CodeNotFound, } public class SCBindBreakpointResult { public int BreakpointHashCode { get; set; } public BindBreakpointResults Result { get; set; } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/Protocol/SCBreakpointHit.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class SCBreakpointHit { public int BreakpointHashCode { get; set; } public int ThreadHashCode { get; set; } public KeyValuePair[] StackFrame { get; set; } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/Protocol/SCModuleLoaded.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class SCModuleLoaded { public string ModuleName { get; set; } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/Protocol/SCResolveVariableResult.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class SCResolveVariableResult { public VariableInfo Info { get; set; } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/Protocol/SCStepComplete.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class SCStepComplete { public int ThreadHashCode { get; set; } public KeyValuePair[] StackFrame { get; set; } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/Protocol/SCThreadStarted.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class SCThreadStarted { public int ThreadHashCode { get; set; } } public class SCThreadEnded { public int ThreadHashCode { get; set; } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/StackFrameInfo.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger { public class StackFrameInfo { public string MethodName { get; set; } public string DocumentName { get; set; } public int StartLine { get; set; } public int StartColumn { get; set; } public int EndLine { get; set; } public int EndColumn { get; set; } public VariableInfo[] LocalVariables { get; set; } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/StepTypes.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger { public enum StepTypes { None, Into, Over, Out, } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Debugger/VariableInfo.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger { public enum VariableTypes { Normal, FieldReference, Error, } public class VariableReference { public long Address { get; set; } public VariableTypes Type { get; set; } public int Offset { get; set; } public VariableReference Parent { get; set; } } public class VariableInfo { public long Address { get; set; } public VariableTypes Type { get; set; } public string Name { get; set; } public string TypeName { get; set; } public string Value { get; set; } public bool Expandable { get; set; } public int Offset { get; set;} } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Enviorment/AppDomain.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using Mono.Cecil; using System.Reflection; using Mono.Cecil.Cil; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.CLR.Utils; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Debugger; using ILRuntime.Runtime.Stack; using ILRuntime.Other; namespace ILRuntime.Runtime.Enviorment { public unsafe delegate StackObject* CLRRedirectionDelegate(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj); public delegate object CLRFieldGetterDelegate(ref object target); public delegate void CLRFieldSetterDelegate(ref object target, object value); public delegate object CLRMemberwiseCloneDelegate(ref object target); public delegate object CLRCreateDefaultInstanceDelegate(); public delegate object CLRCreateArrayInstanceDelegate(int size); public class AppDomain { Queue freeIntepreters = new Queue(); Dictionary intepreters = new Dictionary(); Dictionary crossAdaptors = new Dictionary(new ByReferenceKeyComparer()); Dictionary valueTypeBinders = new Dictionary(); ThreadSafeDictionary mapType = new ThreadSafeDictionary(); Dictionary clrTypeMapping = new Dictionary(new ByReferenceKeyComparer()); ThreadSafeDictionary mapTypeToken = new ThreadSafeDictionary(); ThreadSafeDictionary mapMethod = new ThreadSafeDictionary(); ThreadSafeDictionary mapString = new ThreadSafeDictionary(); Dictionary redirectMap = new Dictionary(); Dictionary fieldGetterMap = new Dictionary(); Dictionary fieldSetterMap = new Dictionary(); Dictionary memberwiseCloneMap = new Dictionary(new ByReferenceKeyComparer()); Dictionary createDefaultInstanceMap = new Dictionary(new ByReferenceKeyComparer()); Dictionary createArrayInstanceMap = new Dictionary(new ByReferenceKeyComparer()); IType voidType, intType, longType, boolType, floatType, doubleType, objectType; DelegateManager dMgr; Assembly[] loadedAssemblies; Dictionary references = new Dictionary(); DebugService debugService; /// /// Determine if invoking unbinded CLR method(using reflection) is allowed /// public bool AllowUnboundCLRMethod { get; set; } #if UNITY_EDITOR public int UnityMainThreadID { get; set; } #endif public unsafe AppDomain() { AllowUnboundCLRMethod = true; loadedAssemblies = System.AppDomain.CurrentDomain.GetAssemblies(); var mi = typeof(System.Runtime.CompilerServices.RuntimeHelpers).GetMethod("InitializeArray"); RegisterCLRMethodRedirection(mi, CLRRedirections.InitializeArray); foreach (var i in typeof(System.Activator).GetMethods()) { if (i.Name == "CreateInstance" && i.IsGenericMethodDefinition) { RegisterCLRMethodRedirection(i, CLRRedirections.CreateInstance); } else if(i.Name == "CreateInstance" && i.GetParameters().Length == 1) { RegisterCLRMethodRedirection(i, CLRRedirections.CreateInstance2); } } foreach (var i in typeof(System.Type).GetMethods()) { if (i.Name == "GetType" && i.IsStatic) { RegisterCLRMethodRedirection(i, CLRRedirections.GetType); } if(i.Name=="Equals" && i.GetParameters()[0].ParameterType == typeof(Type)) { RegisterCLRMethodRedirection(i, CLRRedirections.TypeEquals); } } foreach (var i in typeof(System.Delegate).GetMethods()) { if (i.Name == "Combine" && i.GetParameters().Length == 2) { RegisterCLRMethodRedirection(i, CLRRedirections.DelegateCombine); } if(i.Name == "Remove") { RegisterCLRMethodRedirection(i, CLRRedirections.DelegateRemove); } if(i.Name == "op_Equality") { RegisterCLRMethodRedirection(i, CLRRedirections.DelegateEqulity); } if(i.Name == "op_Inequality") { RegisterCLRMethodRedirection(i, CLRRedirections.DelegateInequlity); } } foreach(var i in typeof(MethodBase).GetMethods()) { if(i.Name == "Invoke" && i.GetParameters().Length == 2) { RegisterCLRMethodRedirection(i, CLRRedirections.MethodInfoInvoke); } } mi = typeof(System.Type).GetMethod("GetTypeFromHandle"); RegisterCLRMethodRedirection(mi, CLRRedirections.GetTypeFromHandle); mi = typeof(object).GetMethod("GetType"); RegisterCLRMethodRedirection(mi, CLRRedirections.ObjectGetType); dMgr = new DelegateManager(this); dMgr.RegisterDelegateConvertor((dele) => { return dele; }); RegisterCrossBindingAdaptor(new Adaptors.AttributeAdaptor()); debugService = new Debugger.DebugService(this); } public IType VoidType { get { return voidType; } } public IType IntType { get { return intType; } } public IType LongType { get { return longType; } } public IType BoolType { get { return boolType; } } public IType FloatType { get { return floatType; } } public IType DoubleType { get { return doubleType; } } public IType ObjectType { get { return objectType; } } /// /// Attention, this property isn't thread safe /// public Dictionary LoadedTypes { get { return mapType.InnerDictionary; } } internal Dictionary RedirectMap { get { return redirectMap; } } internal Dictionary FieldGetterMap { get { return fieldGetterMap; } } internal Dictionary FieldSetterMap { get { return fieldSetterMap; } } internal Dictionary MemberwiseCloneMap { get { return memberwiseCloneMap; } } internal Dictionary CreateDefaultInstanceMap { get { return createDefaultInstanceMap; } } internal Dictionary CreateArrayInstanceMap { get { return createArrayInstanceMap; } } internal Dictionary CrossBindingAdaptors { get { return crossAdaptors; } } internal Dictionary ValueTypeBinders { get { return valueTypeBinders; } } public DebugService DebugService { get { return debugService; } } internal Dictionary Intepreters { get { return intepreters; } } internal Queue FreeIntepreters { get { return freeIntepreters; } } public DelegateManager DelegateManager { get { return dMgr; } } /// /// 加载Assembly 文件,从指定的路径 /// /// 路径 public void LoadAssemblyFile(string path) { FileInfo file = new FileInfo(path); if (!file.Exists) { throw new FileNotFoundException(string.Format("Assembly File not find!:\r\n{0}", path)); } else { using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) { LoadAssembly(fs); fs.Dispose(); } } } #if USE_MDB || USE_PDB /// /// 加载Assembly 文件和PDB文件或MDB文件,从指定的路径(PDB和MDB文件按默认命名方式,并且和Assembly文件处于同一目录中 /// /// 路径 public void LoadAssemblyFileAndSymbol(string path) { FileInfo file = new FileInfo(path); if (!file.Exists) { throw new FileNotFoundException(string.Format("Assembly File not find!:\r\n{0}", path)); } else { var dlldir = file.DirectoryName; var assname = Path.GetFileNameWithoutExtension(file.Name); var pdbpath = string.Format("{0}/{1}.pdb",dlldir,assname); var mdbpath = string.Format("{0}/{1}.mdb", dlldir, assname); string symbolPath = ""; bool isPDB = true; if (File.Exists(pdbpath)) { symbolPath = pdbpath; } else if (File.Exists(mdbpath)) { symbolPath = mdbpath; isPDB = false; } if (string.IsNullOrEmpty(symbolPath)) { throw new FileNotFoundException(string.Format("symbol file not find!:\r\ncheck:\r\n{0}\r\n{1}\r\n", pdbpath,mdbpath)); } using (FileStream fs = new FileStream(file.FullName, FileMode.Open, FileAccess.Read)) { using (var pdbfs = new System.IO.FileStream(symbolPath, FileMode.Open)) { if (isPDB) { LoadAssemblyPDB(fs, pdbfs); } else { LoadAssemblyMDB(fs, pdbfs); } } } } } #endif #if USE_PDB /// /// 加载Assembly 文件和PDB文件,两者都从指定的路径 /// /// Assembly 文件路径 /// symbol文件路径 public void LoadAssemblyFileAndPDB(string assemblyFilePath,string symbolFilePath) { FileInfo assfile = new FileInfo(assemblyFilePath); FileInfo pdbfile = new FileInfo(symbolFilePath); if (!assfile.Exists) { throw new FileNotFoundException(string.Format("Assembly File not find!:\r\n{0}", assemblyFilePath)); } if (!pdbfile.Exists) { throw new FileNotFoundException(string.Format("symbol file not find!:\r\n{0}", symbolFilePath)); } using (FileStream fs = new FileStream(assfile.FullName, FileMode.Open, FileAccess.Read)) { using (var pdbfs = new System.IO.FileStream(pdbfile.FullName, FileMode.Open)) { LoadAssemblyPDB(fs, pdbfs); } } } /// /// 从流加载Assembly,以及symbol符号文件(pdb) /// /// Assembly Stream /// PDB Stream public void LoadAssemblyPDB(System.IO.Stream stream, System.IO.Stream symbol) { LoadAssembly(stream, symbol, new Mono.Cecil.Pdb.PdbReaderProvider()); } #endif #if USE_MDB /// /// 加载Assembly 文件和MDB文件,两者都从指定的路径 /// /// Assembly 文件路径 /// symbol文件路径 public void LoadAssemblyFileAndMDB(string assemblyFilePath, string symbolFilePath) { FileInfo assfile = new FileInfo(assemblyFilePath); FileInfo pdbfile = new FileInfo(symbolFilePath); if (!assfile.Exists) { throw new FileNotFoundException(string.Format("Assembly File not find!:\r\n{0}", assemblyFilePath)); } if (!pdbfile.Exists) { throw new FileNotFoundException(string.Format("symbol file not find!:\r\n{0}", symbolFilePath)); } using (FileStream fs = new FileStream(assfile.FullName, FileMode.Open, FileAccess.Read)) { using (var pdbfs = new System.IO.FileStream(pdbfile.FullName, FileMode.Open)) { LoadAssemblyMDB(fs, pdbfs); } } } /// /// 从流加载Assembly,以及symbol符号文件(Mdb) /// /// Assembly Stream /// PDB Stream public void LoadAssemblyMDB(System.IO.Stream stream, System.IO.Stream symbol) { LoadAssembly(stream, symbol, new Mono.Cecil.Mdb.MdbReaderProvider()); } #endif /// /// 从流加载Assembly 不加载symbol符号文件 /// /// Dll数据流 public void LoadAssembly(System.IO.Stream stream) { LoadAssembly(stream, null, null); } /// /// 从流加载Assembly,以及symbol符号文件(pdb) /// /// Assembly Stream /// symbol Stream /// symbol 读取器 public void LoadAssembly(System.IO.Stream stream, System.IO.Stream symbol, ISymbolReaderProvider symbolReader) { var module = ModuleDefinition.ReadModule(stream); //从MONO中加载模块 if (symbolReader != null && symbol != null) { module.ReadSymbols(symbolReader.GetSymbolReader(module, symbol)); //加载符号表 } if (module.HasAssemblyReferences) //如果此模块引用了其他模块 { foreach (var ar in module.AssemblyReferences) { /*if (moduleref.Contains(ar.Name) == false) moduleref.Add(ar.Name); if (moduleref.Contains(ar.FullName) == false) moduleref.Add(ar.FullName);*/ } } if (module.HasTypes) { List types = new List(); foreach (var t in module.GetTypes()) //获取所有此模块定义的类型 { ILType type = new ILType(t, this); mapType[t.FullName] = type; types.Add(type); } } if (voidType == null) { voidType = GetType("System.Void"); intType = GetType("System.Int32"); longType = GetType("System.Int64"); boolType = GetType("System.Boolean"); floatType = GetType("System.Single"); doubleType = GetType("System.Double"); objectType = GetType("System.Object"); } module.AssemblyResolver.ResolveFailure += AssemblyResolver_ResolveFailure; #if DEBUG debugService.NotifyModuleLoaded(module.Name); #endif } /// /// External reference should be added to the AppDomain by the method /// /// Assembly name, without .dll /// file content public void AddReferenceBytes(string name, byte[] content) { references[name] = content; } private AssemblyDefinition AssemblyResolver_ResolveFailure(object sender, AssemblyNameReference reference) { byte[] content; if (references.TryGetValue(reference.Name, out content)) { using (System.IO.MemoryStream ms = new System.IO.MemoryStream(content)) { return AssemblyDefinition.ReadAssembly(ms); } } else return null; } public void RegisterCLRMethodRedirection(MethodBase mi, CLRRedirectionDelegate func) { if (!redirectMap.ContainsKey(mi)) redirectMap[mi] = func; } public void RegisterCLRFieldGetter(FieldInfo f, CLRFieldGetterDelegate getter) { if (!fieldGetterMap.ContainsKey(f)) fieldGetterMap[f] = getter; } public void RegisterCLRFieldSetter(FieldInfo f, CLRFieldSetterDelegate setter) { if (!fieldSetterMap.ContainsKey(f)) fieldSetterMap[f] = setter; } public void RegisterCLRMemberwiseClone(Type t, CLRMemberwiseCloneDelegate memberwiseClone) { if (!memberwiseCloneMap.ContainsKey(t)) memberwiseCloneMap[t] = memberwiseClone; } public void RegisterCLRCreateDefaultInstance(Type t, CLRCreateDefaultInstanceDelegate createDefaultInstance) { if (!createDefaultInstanceMap.ContainsKey(t)) createDefaultInstanceMap[t] = createDefaultInstance; } public void RegisterCLRCreateArrayInstance(Type t, CLRCreateArrayInstanceDelegate createArray) { if (!createArrayInstanceMap.ContainsKey(t)) createArrayInstanceMap[t] = createArray; } public void RegisterValueTypeBinder(Type t, ValueTypeBinder binder) { if (!valueTypeBinders.ContainsKey(t)) { valueTypeBinders[t] = binder; binder.RegisterCLRRedirection(this); } } /// /// 更近类型名称返回类型 /// /// 类型全名 命名空间.类型名 /// public IType GetType(string fullname) { IType res; if (fullname == null) { return null; } if (mapType.TryGetValue(fullname, out res)) return res; string baseType; List genericParams; bool isArray; ParseGenericType(fullname, out baseType, out genericParams, out isArray); bool isByRef = baseType.EndsWith("&"); if (isByRef) baseType = baseType.Substring(0, baseType.Length - 1); if (genericParams != null || isArray || isByRef) { IType bt = GetType(baseType); if (bt == null) { bt = GetType(baseType.Replace("/", "+")); } if (bt == null) return null; if (genericParams != null) { KeyValuePair[] genericArguments = new KeyValuePair[genericParams.Count]; for (int i = 0; i < genericArguments.Length; i++) { string key = "!" + i; IType val = GetType(genericParams[i]); if (val == null) return null; genericArguments[i] = new KeyValuePair(key, val); } bt = bt.MakeGenericInstance(genericArguments); mapType[bt.FullName] = bt; mapTypeToken[bt.GetHashCode()] = bt; StringBuilder sb = new StringBuilder(); sb.Append(baseType); sb.Append('<'); for (int i = 0; i < genericParams.Count; i++) { if (i > 0) sb.Append(","); if (genericParams[i].Contains(",")) sb.Append(genericParams[i].Substring(0, genericParams[i].IndexOf(','))); else sb.Append(genericParams[i]); } sb.Append('>'); var asmName = sb.ToString(); if (bt.FullName != asmName) mapType[asmName] = bt; } if (isArray) { bt = bt.MakeArrayType(); mapType[bt.FullName] = bt; mapTypeToken[bt.GetHashCode()] = bt; if (!isByRef) { mapType[fullname] = bt; return bt; } } if (isByRef) { res = bt.MakeByRefType(); mapType[fullname] = res; mapType[res.FullName] = res; mapTypeToken[res.GetHashCode()] = res; return res; } else { mapType[fullname] = bt; return bt; } } else { Type t = Type.GetType(fullname); if (t != null) { if (!clrTypeMapping.TryGetValue(t, out res)) { res = new CLRType(t, this); clrTypeMapping[t] = res; } mapType[fullname] = res; mapType[res.FullName] = res; mapType[t.AssemblyQualifiedName] = res; mapTypeToken[res.GetHashCode()] = res; return res; } } return null; } internal static void ParseGenericType(string fullname, out string baseType, out List genericParams, out bool isArray) { StringBuilder sb = new StringBuilder(); int depth = 0; baseType = ""; genericParams = null; if (fullname.Length >2 && fullname.Substring(fullname.Length - 2) == "[]") { fullname = fullname.Substring(0, fullname.Length - 2); isArray = true; } else isArray = false; if (fullname.Contains('<') || fullname.Contains('[')) { foreach (var i in fullname) { if (i == '<' || i == '[') { depth++; if (depth == 1) { baseType = sb.ToString(); sb.Length = 0; genericParams = new List(); continue; } } if (i == ',' && depth == 1) { string name = sb.ToString(); if (name.StartsWith("[")) name = name.Substring(1, name.Length - 2); if (!string.IsNullOrEmpty(name)) genericParams.Add(name); sb.Length = 0; continue; } if (i == '>' || i == ']') { depth--; if (depth == 0) { string name = sb.ToString(); if (name.StartsWith("[")) name = name.Substring(1, name.Length - 2); if (!string.IsNullOrEmpty(name)) genericParams.Add(name); else { if (!isArray) { isArray = true; } else { baseType += "[]"; } } sb.Length = 0; continue; } } sb.Append(i); } if (sb.Length > 0) { baseType += sb.ToString(); } if (genericParams != null && genericParams.Count == 0) genericParams = null; } else baseType = fullname; } string GetAssemblyName(IMetadataScope scope) { return scope is AssemblyNameReference ? ((AssemblyNameReference)scope).FullName : null; } internal IType GetType(object token, IType contextType, IMethod contextMethod) { int hash = token.GetHashCode(); IType res; if (mapTypeToken.TryGetValue(hash, out res)) return res; Mono.Cecil.ModuleDefinition module = null; KeyValuePair[] genericArguments = null; string typename = null; string scope = null; bool dummyGenericInstance = false; if (token is Mono.Cecil.TypeDefinition) { Mono.Cecil.TypeDefinition _def = (token as Mono.Cecil.TypeDefinition); module = _def.Module; typename = _def.FullName; scope = GetAssemblyName(_def.Scope); } else if (token is Mono.Cecil.TypeReference) { Mono.Cecil.TypeReference _ref = (token as Mono.Cecil.TypeReference); if (_ref.IsGenericParameter) { IType t = null; if (contextType != null) { t = contextType.FindGenericArgument(_ref.Name); } if (t == null && contextMethod != null && contextMethod is ILMethod) { t = ((ILMethod)contextMethod).FindGenericArgument(_ref.Name); } return t; } if (_ref.IsByReference) { var et = _ref.GetElementType(); bool valid = !et.IsGenericParameter; var t = GetType(et, contextType, contextMethod); if (t != null) { res = t.MakeByRefType(); if (res is ILType && valid) { ///Unify the TypeReference ((ILType)res).TypeReference = _ref; } if (valid) mapTypeToken[hash] = res; if (!string.IsNullOrEmpty(res.FullName)) mapType[res.FullName] = res; return res; } return null; } if (_ref.IsArray) { var t = GetType(_ref.GetElementType(), contextType, contextMethod); if (t != null) { res = t.MakeArrayType(); if (res is ILType) { ///Unify the TypeReference ((ILType)res).TypeReference = _ref; } mapTypeToken[hash] = res; if (!string.IsNullOrEmpty(res.FullName)) mapType[res.FullName] = res; return res; } return t; } module = _ref.Module; if (_ref.IsGenericInstance) { GenericInstanceType gType = (GenericInstanceType)_ref; typename = gType.ElementType.FullName; scope = GetAssemblyName(gType.ElementType.Scope); TypeReference tr = gType.ElementType; genericArguments = new KeyValuePair[gType.GenericArguments.Count]; for (int i = 0; i < genericArguments.Length; i++) { string key = tr.GenericParameters[i].Name; IType val; if (gType.GenericArguments[i].IsGenericParameter) { val = contextType.FindGenericArgument(gType.GenericArguments[i].Name); dummyGenericInstance = true; if (val == null) { if (contextMethod != null && contextMethod is ILMethod) { val = ((ILMethod)contextMethod).FindGenericArgument(gType.GenericArguments[i].Name); } else return null; } } else val = GetType(gType.GenericArguments[i], contextType, contextMethod); if (val != null && val.HasGenericParameter) dummyGenericInstance = true; if (val != null) genericArguments[i] = new KeyValuePair(key, val); else { genericArguments = null; break; } } } else { typename = _ref.FullName; scope = GetAssemblyName(_ref.Scope); } } else { throw new NotImplementedException(); } res = GetType(typename); if (res == null) { typename = typename.Replace("/", "+"); res = GetType(typename); } if (res == null && scope != null) res = GetType(typename + ", " + scope); if (res == null) { if (scope != null) { string aname = scope.Split(',')[0]; foreach (var i in loadedAssemblies) { if (aname == i.GetName().Name) { res = GetType(typename + ", " + i.FullName); if (res != null) break; } } } if (res == null) { foreach (var j in loadedAssemblies) { res = GetType(typename + ", " + j.FullName); if (res != null) break; } } if (res != null && scope != null) { mapType[typename + ", " + scope] = res; } } if (res == null) throw new KeyNotFoundException("Cannot find Type:" + typename); if (genericArguments != null) { res = res.MakeGenericInstance(genericArguments); if (!dummyGenericInstance && res is ILType) { ((ILType)res).TypeReference = (TypeReference)token; } if (!string.IsNullOrEmpty(res.FullName)) { if (res is CLRType || !((ILType)res).TypeReference.HasGenericParameters) mapType[res.FullName] = res; } } mapTypeToken[res.GetHashCode()] = res; if (!dummyGenericInstance) mapTypeToken[hash] = res; return res; } public IType GetType(int hash) { IType res; if (mapTypeToken.TryGetValue(hash, out res)) return res; else return null; } /// /// 根据CLR类型获取 IL类型 /// /// /// public IType GetType(Type t) { IType res; if (clrTypeMapping.TryGetValue(t, out res)) return res; else return GetType(t.AssemblyQualifiedName); } /// /// Create a instance of the specified type, which is inherited from a CLR Type /// /// CLR Type /// Full Name of the type /// Arguments for the constructor /// public T Instantiate(string type, object[] args = null) { ILTypeInstance ins = Instantiate(type, args); return (T)ins.CLRInstance; } /// /// Create a instance of the specified type /// /// Full Name of the type /// Arguments for the constructor /// public ILTypeInstance Instantiate(string type, object[] args = null) { IType t; if (mapType.TryGetValue(type, out t)) { ILType ilType = t as ILType; if(ilType != null) { bool hasConstructor = args != null && args.Length != 0; var res = ilType.Instantiate(!hasConstructor); if (hasConstructor) { var ilm = ilType.GetConstructor(args.Length); Invoke(ilm, res, args); } return res; } } return null; } /// /// Invoke a method /// /// Type's fullname /// Method name /// Parameters /// public object Invoke(string type, string method, object instance, params object[] p) { IType t = GetType(type); if (t == null) return null; var m = t.GetMethod(method, p != null ? p.Length : 0); if (m != null) { for(int i = 0; i < m.ParameterCount; i++) { if (p[i] == null) continue; if (!m.Parameters[i].TypeForCLR.IsAssignableFrom(p[i].GetType())) { throw new ArgumentException("Parameter type mismatch"); } } return Invoke(m, instance, p); } return null; } /// /// Invoke a generic method /// /// Type's fullname /// Method name /// Generic Arguments /// Object Instance of the method /// Parameters /// public object InvokeGenericMethod(string type, string method, IType[] genericArguments, object instance, params object[] p) { IType t = GetType(type); if (t == null) return null; var m = t.GetMethod(method, p.Length); if (m != null) { m = m.MakeGenericMethod(genericArguments); return Invoke(m, instance, p); } return null; } /// /// Invokes a specific method /// /// Method /// object instance /// Parameters /// public object Invoke(IMethod m, object instance, params object[] p) { object res = null; if (m is ILMethod) { ILIntepreter inteptreter = null; lock (freeIntepreters) { if (freeIntepreters.Count > 0) { inteptreter = freeIntepreters.Dequeue(); //Clear debug state, because it may be in ShouldBreak State inteptreter.ClearDebugState(); } else { inteptreter = new ILIntepreter(this); #if DEBUG intepreters[inteptreter.GetHashCode()] = inteptreter; debugService.ThreadStarted(inteptreter); #endif } } try { res = inteptreter.Run((ILMethod)m, instance, p); } finally { lock (freeIntepreters) { #if DEBUG if(inteptreter.CurrentStepType!= StepTypes.None) { //We should resume all other threads if we are currently doing stepping operation foreach(var i in intepreters) { if(i.Value != inteptreter) { i.Value.ClearDebugState(); i.Value.Resume(); } } inteptreter.ClearDebugState(); } #endif inteptreter.Stack.ManagedStack.Clear(); inteptreter.Stack.Frames.Clear(); freeIntepreters.Enqueue(inteptreter); #if DEBUG //debugService.ThreadEnded(inteptreter); #endif } } } return res; } internal IMethod GetMethod(object token, ILType contextType,ILMethod contextMethod, out bool invalidToken) { string methodname = null; string typename = null; List paramList = null; int hashCode = token.GetHashCode(); IMethod method; IType[] genericArguments = null; IType returnType; invalidToken = false; bool isConstructor = false; if (mapMethod.TryGetValue(hashCode, out method)) return method; IType type = null; if (token is Mono.Cecil.MethodReference) { Mono.Cecil.MethodReference _ref = (token as Mono.Cecil.MethodReference); if (_ref.FullName == "System.Void System.Object::.ctor()") { mapMethod[hashCode] = null; return null; } if (_ref.FullName == "System.Void System.Attribute::.ctor()") { mapMethod[hashCode] = null; return null; } methodname = _ref.Name; var typeDef = _ref.DeclaringType; type = GetType(typeDef, contextType, contextMethod); if (type == null) throw new KeyNotFoundException("Cannot find type:" + typename); if (token is Mono.Cecil.MethodDefinition) { var def = _ref as MethodDefinition; isConstructor = def.IsConstructor; } else isConstructor = methodname == ".ctor"; if (_ref.IsGenericInstance) { GenericInstanceMethod gim = (GenericInstanceMethod)_ref; genericArguments = new IType[gim.GenericArguments.Count]; for (int i = 0; i < genericArguments.Length; i++) { if (gim.GenericArguments[i].IsGenericParameter) invalidToken = true; var gt = GetType(gim.GenericArguments[i], contextType, contextMethod); if (gt == null) { gt = contextMethod.FindGenericArgument(gim.GenericArguments[i].Name); if (gt == null)//This means it contains unresolved generic arguments, which means it's not searching the generic instance { genericArguments = null; break; } else genericArguments[i] = gt; } else genericArguments[i] = gt; } } if (!invalidToken && typeDef.IsGenericInstance) { GenericInstanceType gim = (GenericInstanceType)typeDef; for (int i = 0; i < gim.GenericArguments.Count; i++) { if (gim.GenericArguments[0].IsGenericParameter) { invalidToken = true; break; } } } paramList = _ref.GetParamList(this, contextType, contextMethod, genericArguments); returnType = GetType(_ref.ReturnType, type, null); if (returnType == null) returnType = GetType(_ref.ReturnType, contextType, null); } else { throw new NotImplementedException(); //Mono.Cecil.GenericInstanceMethod gmethod = _def as Mono.Cecil.GenericInstanceMethod; //genlist = new MethodParamList(environment, gmethod); } if (isConstructor) method = type.GetConstructor(paramList); else { method = type.GetMethod(methodname, paramList, genericArguments, returnType, true); } if (method == null) { if (isConstructor && contextType.FirstCLRBaseType != null && contextType.FirstCLRBaseType is CrossBindingAdaptor && type.TypeForCLR == ((CrossBindingAdaptor)contextType.FirstCLRBaseType).BaseCLRType) { method = contextType.BaseType.GetConstructor(paramList); if (method == null) throw new KeyNotFoundException(string.Format("Cannot find method:{0} in type:{1}, token={2}", methodname, type.FullName, token)); invalidToken = true; mapMethod[method.GetHashCode()] = method; } else throw new KeyNotFoundException(string.Format("Cannot find method:{0} in type:{1}, token={2}", methodname, type.FullName, token)); } if (!invalidToken) mapMethod[hashCode] = method; else mapMethod[method.GetHashCode()] = method; return method; } internal IMethod GetMethod(int tokenHash) { IMethod res; if (mapMethod.TryGetValue(tokenHash, out res)) return res; return null; } internal long GetStaticFieldIndex(object token, IType contextType, IMethod contextMethod) { FieldReference f = token as FieldReference; var type = GetType(f.DeclaringType, contextType, contextMethod); if (type is ILType) { var it = type as ILType; int idx = it.GetFieldIndex(token); long res = 0; if (it.TypeReference.HasGenericParameters) { mapTypeToken[type.GetHashCode()] = it; res = ((long)type.GetHashCode() << 32) | (uint)idx; } else { res = ((long)it.TypeReference.GetHashCode() << 32) | (uint)idx; } return res; } else { int idx = type.GetFieldIndex(token); long res = ((long)type.GetHashCode() << 32) | (uint)idx; return res; } } internal long CacheString(object token) { long oriHash = token.GetHashCode(); long hashCode = oriHash; string str = (string)token; lock (mapString) { bool isCollision = CheckStringCollision(hashCode, str); long cnt = 0; while (isCollision) { cnt++; hashCode = cnt << 32 | oriHash; isCollision = CheckStringCollision(hashCode, str); } mapString[hashCode] = (string)token; } return hashCode; } bool CheckStringCollision(long hashCode, string newStr) { string oldVal; if (mapString.TryGetValue(hashCode, out oldVal)) return oldVal != newStr; return false; } internal string GetString(long hashCode) { string res = null; if (mapString.TryGetValue(hashCode, out res)) return res; return res; } public void RegisterCrossBindingAdaptor(CrossBindingAdaptor adaptor) { var bType = adaptor.BaseCLRType; if (bType != null) { if (!crossAdaptors.ContainsKey(bType)) { var t = adaptor.AdaptorType; var res = GetType(t); if (res == null) { res = new CLRType(t, this); mapType[res.FullName] = res; mapType[t.AssemblyQualifiedName] = res; clrTypeMapping[t] = res; } adaptor.RuntimeType = res; crossAdaptors[bType] = adaptor; } else throw new Exception("Crossbinding Adapter for " + bType.FullName + " is already added."); } else { var bTypes = adaptor.BaseCLRTypes; var t = adaptor.AdaptorType; var res = GetType(t); if (res == null) { res = new CLRType(t, this); mapType[res.FullName] = res; mapType[t.AssemblyQualifiedName] = res; clrTypeMapping[t] = res; } adaptor.RuntimeType = res; foreach (var i in bTypes) { if (!crossAdaptors.ContainsKey(i)) { crossAdaptors[i] = adaptor; } else throw new Exception("Crossbinding Adapter for " + i.FullName + " is already added."); } } } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Enviorment/CLRRedirections.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.CLR.Utils; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Stack; using ILRuntime.Reflection; namespace ILRuntime.Runtime.Enviorment { unsafe static class CLRRedirections { public static StackObject* CreateInstance(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { IType[] genericArguments = method.GenericArguments; if (genericArguments != null && genericArguments.Length == 1) { var t = genericArguments[0]; if (t is ILType) { return ILIntepreter.PushObject(esp, mStack, ((ILType)t).Instantiate()); } else return ILIntepreter.PushObject(esp, mStack, ((CLRType)t).CreateDefaultInstance()); } else throw new EntryPointNotFoundException(); } /*public static object CreateInstance(ILContext ctx, object instance, object[] param, IType[] genericArguments) { if (genericArguments != null && genericArguments.Length == 1) { var t = genericArguments[0]; if (t is ILType) { return ((ILType)t).Instantiate(); } else return Activator.CreateInstance(t.TypeForCLR); } else throw new EntryPointNotFoundException(); }*/ public static StackObject* CreateInstance2(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { var p = esp - 1; var t = mStack[p->Value] as Type; intp.Free(p); if (t != null) { if (t is ILRuntimeType) { return ILIntepreter.PushObject(p, mStack, ((ILRuntimeType)t).ILType.Instantiate()); } else return ILIntepreter.PushObject(p, mStack, Activator.CreateInstance(t)); } else return ILIntepreter.PushNull(p); } /*public static object CreateInstance2(ILContext ctx, object instance, object[] param, IType[] genericArguments) { var t = param[0] as Type; if (t != null) { if (t is ILRuntimeType) { return ((ILRuntimeType)t).ILType.Instantiate(); } else return Activator.CreateInstance(t); } else return null; }*/ public static StackObject* GetType(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { var p = esp - 1; AppDomain dommain = intp.AppDomain; string fullname = (string)StackObject.ToObject(p, dommain, mStack); ; intp.Free(p); var t = intp.AppDomain.GetType(fullname); if (t != null) return ILIntepreter.PushObject(p, mStack, t.ReflectionType); else return ILIntepreter.PushNull(p); } public static StackObject* TypeEquals(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { var ret = ILIntepreter.Minus(esp, 2); var p = esp - 1; AppDomain dommain = intp.AppDomain; var other = StackObject.ToObject(p, dommain, mStack); intp.Free(p); p = ILIntepreter.Minus(esp, 2); var instance = StackObject.ToObject(p, dommain, mStack); intp.Free(p); if(instance is ILRuntimeType) { if (other is ILRuntimeType) { if(((ILRuntimeType)instance).ILType == ((ILRuntimeType)other).ILType) return ILIntepreter.PushOne(ret); else return ILIntepreter.PushZero(ret); } else return ILIntepreter.PushZero(ret); } else { if(((Type)typeof(Type).CheckCLRTypes(instance)).Equals(((Type)typeof(Type).CheckCLRTypes(other)))) return ILIntepreter.PushOne(ret); else return ILIntepreter.PushZero(ret); } } /*public static object GetType(ILContext ctx, object instance, object[] param, IType[] genericArguments) { var t = ctx.AppDomain.GetType((string)param[0]); if (t != null) return t.ReflectionType; else return null; }*/ public unsafe static StackObject* InitializeArray(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var param = esp - 1; byte[] data = StackObject.ToObject(param, domain, mStack) as byte[]; intp.Free(param); param = esp - 1 - 1; object array = StackObject.ToObject(param, domain, mStack); intp.Free(param); if (data == null) return ret; fixed (byte* p = data) { if (array is int[]) { int[] arr = array as int[]; int* ptr = (int*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is byte[]) { byte[] arr = array as byte[]; for (int i = 0; i < arr.Length; i++) { arr[i] = p[i]; } } else if (array is sbyte[]) { sbyte[] arr = array as sbyte[]; sbyte* ptr = (sbyte*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is short[]) { short[] arr = array as short[]; short* ptr = (short*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is ushort[]) { ushort[] arr = array as ushort[]; ushort* ptr = (ushort*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is char[]) { char[] arr = array as char[]; char* ptr = (char*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is uint[]) { uint[] arr = array as uint[]; uint* ptr = (uint*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is Int64[]) { long[] arr = array as long[]; long* ptr = (long*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is UInt64[]) { ulong[] arr = array as ulong[]; ulong* ptr = (ulong*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is float[]) { float[] arr = array as float[]; float* ptr = (float*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is double[]) { double[] arr = array as double[]; double* ptr = (double*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is bool[]) { bool[] arr = array as bool[]; bool* ptr = (bool*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else { throw new NotImplementedException("array=" + array.GetType()); } } return ret; } /*public unsafe static object InitializeArray(ILContext ctx, object instance, object[] param, IType[] genericArguments) { object array = param[0]; byte[] data = param[1] as byte[]; if (data == null) return null; fixed (byte* p = data) { if (array is int[]) { int[] arr = array as int[]; int* ptr = (int*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is byte[]) { byte[] arr = array as byte[]; for (int i = 0; i < arr.Length; i++) { arr[i] = p[i]; } } else if (array is sbyte[]) { sbyte[] arr = array as sbyte[]; sbyte* ptr = (sbyte*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is short[]) { short[] arr = array as short[]; short* ptr = (short*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is ushort[]) { ushort[] arr = array as ushort[]; ushort* ptr = (ushort*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is char[]) { char[] arr = array as char[]; char* ptr = (char*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is uint[]) { uint[] arr = array as uint[]; uint* ptr = (uint*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is Int64[]) { long[] arr = array as long[]; long* ptr = (long*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is UInt64[]) { ulong[] arr = array as ulong[]; ulong* ptr = (ulong*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is float[]) { float[] arr = array as float[]; float* ptr = (float*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is double[]) { double[] arr = array as double[]; double* ptr = (double*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is bool[]) { bool[] arr = array as bool[]; bool* ptr = (bool*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else { throw new NotImplementedException("array=" + array.GetType()); } } return null; }*/ public unsafe static StackObject* DelegateCombine(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { //Don't ask me why not esp -2, unity won't return the right result var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var param = esp - 1; object dele2 = StackObject.ToObject(param, domain, mStack); intp.Free(param); param = esp - 1 - 1; object dele1 = StackObject.ToObject(param, domain, mStack); intp.Free(param); if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) { var dele = ((IDelegateAdapter)dele1); //This means it's the original delegate which should be untouch if (!dele.IsClone) { dele = dele.Clone(); } if(!((IDelegateAdapter)dele2).IsClone) { dele2 = ((IDelegateAdapter)dele2).Clone(); } dele.Combine((IDelegateAdapter)dele2); return ILIntepreter.PushObject(ret, mStack, dele); } else { if (!((IDelegateAdapter)dele1).IsClone) { dele1 = ((IDelegateAdapter)dele1).Clone(); } ((IDelegateAdapter)dele1).Combine((Delegate)dele2); return ILIntepreter.PushObject(ret, mStack, dele1); } } else { if (dele2 is IDelegateAdapter) return ILIntepreter.PushObject(ret, mStack, Delegate.Combine((Delegate)dele1, ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType()))); else return ILIntepreter.PushObject(ret, mStack, Delegate.Combine((Delegate)dele1, (Delegate)dele2)); } } else return ILIntepreter.PushObject(ret, mStack, dele1); } else return ILIntepreter.PushObject(ret, mStack, dele2); } /*public unsafe static object DelegateCombine(ILContext ctx, object instance, object[] param, IType[] genericArguments) { var esp = ctx.ESP; var mStack = ctx.ManagedStack; var domain = ctx.AppDomain; //Don't ask me why not esp -2, unity won't return the right result var dele1 = StackObject.ToObject((esp - 1 - 1), domain, mStack); var dele2 = StackObject.ToObject((esp - 1), domain, mStack); if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) { var dele = ((IDelegateAdapter)dele1); //This means it's the default delegate which should be singleton to support == operator if (dele.Next == null) { dele = dele.Instantiate(domain, dele.Instance, dele.Method); } dele.Combine((IDelegateAdapter)dele2); return dele; } else { ((IDelegateAdapter)dele1).Combine((Delegate)dele2); return dele1; } } else { if (dele2 is IDelegateAdapter) return Delegate.Combine((Delegate)dele1, ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType())); else return Delegate.Combine((Delegate)dele1, (Delegate)dele2); } } else return dele1; } else return dele2; }*/ public unsafe static StackObject* DelegateRemove(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { //Don't ask me why not esp -2, unity won't return the right result var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var param = esp - 1; object dele2 = StackObject.ToObject(param, domain, mStack); intp.Free(param); param = esp - 1 - 1; object dele1 = StackObject.ToObject(param, domain, mStack); intp.Free(param); if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) { if (((IDelegateAdapter)dele1).Equals((IDelegateAdapter)dele2)) return ILIntepreter.PushObject(ret, mStack, ((IDelegateAdapter)dele1).Next); else ((IDelegateAdapter)dele1).Remove((IDelegateAdapter)dele2); } else ((IDelegateAdapter)dele1).Remove((Delegate)dele2); return ILIntepreter.PushObject(ret, mStack, dele1); } else { if (dele2 is IDelegateAdapter) return ILIntepreter.PushObject(ret, mStack, Delegate.Remove((Delegate)dele1, ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType()))); else return ILIntepreter.PushObject(ret, mStack, Delegate.Remove((Delegate)dele1, (Delegate)dele2)); } } else return ILIntepreter.PushObject(ret, mStack, dele1); } else return ILIntepreter.PushNull(ret); } /*public unsafe static object DelegateRemove(ILContext ctx, object instance, object[] param, IType[] genericArguments) { var esp = ctx.ESP; var mStack = ctx.ManagedStack; var domain = ctx.AppDomain; var dele1 = StackObject.ToObject((esp - 1 - 1), domain, mStack); var dele2 = StackObject.ToObject((esp - 1), domain, mStack); if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) { if (dele1 == dele2) return ((IDelegateAdapter)dele1).Next; else ((IDelegateAdapter)dele1).Remove((IDelegateAdapter)dele2); } else ((IDelegateAdapter)dele1).Remove((Delegate)dele2); return dele1; } else { if (dele2 is IDelegateAdapter) return Delegate.Remove((Delegate)dele1, ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType())); else return Delegate.Remove((Delegate)dele1, (Delegate)dele2); } } else return dele1; } else return null; }*/ public unsafe static StackObject* DelegateEqulity(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { //Don't ask me why not esp -2, unity won't return the right result var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var param = esp - 1; object dele2 = StackObject.ToObject(param, domain, mStack); intp.Free(param); param = esp - 1 - 1; object dele1 = StackObject.ToObject(param, domain, mStack); intp.Free(param); bool res = false; if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) res = ((IDelegateAdapter)dele1).Equals((IDelegateAdapter)dele2); else res = ((IDelegateAdapter)dele1).Equals((Delegate)dele2); } else { if (dele2 is IDelegateAdapter) { res = (Delegate)dele1 == ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType()); } else res = (Delegate)dele1 == (Delegate)dele2; } } else res = dele1 == null; } else res = dele2 == null; if (res) return ILIntepreter.PushOne(ret); else return ILIntepreter.PushZero(ret); } /*public unsafe static object DelegateEqulity(ILContext ctx, object instance, object[] param, IType[] genericArguments) { //op_Equality,op_Inequality var esp = ctx.ESP; var mStack = ctx.ManagedStack; var domain = ctx.AppDomain; var dele1 = StackObject.ToObject((esp - 1 - 1), domain, mStack); var dele2 = StackObject.ToObject((esp - 1), domain, mStack); if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) return ((IDelegateAdapter)dele1).Equals((IDelegateAdapter)dele2); else return ((IDelegateAdapter)dele1).Equals((Delegate)dele2); } else { if (dele2 is IDelegateAdapter) { return (Delegate)dele1 == ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType()); } else return (Delegate)dele1 == (Delegate)dele2; } } else return dele1 == null; } else return dele2 == null; }*/ public unsafe static StackObject* DelegateInequlity(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { //Don't ask me why not esp -2, unity won't return the right result var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var param = esp - 1; object dele2 = StackObject.ToObject(param, domain, mStack); intp.Free(param); param = esp - 1 - 1; object dele1 = StackObject.ToObject(param, domain, mStack); intp.Free(param); bool res = false; if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) res = !((IDelegateAdapter)dele1).Equals((IDelegateAdapter)dele2); else res = !((IDelegateAdapter)dele1).Equals((Delegate)dele2); } else { if (dele2 is IDelegateAdapter) res = (Delegate)dele1 != ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType()); else res = (Delegate)dele1 != (Delegate)dele2; } } else res = dele1 != null; } else res = dele2 != null; if (res) return ILIntepreter.PushOne(ret); else return ILIntepreter.PushZero(ret); } /*public unsafe static object DelegateInequlity(ILContext ctx, object instance, object[] param, IType[] genericArguments) { //op_Equality,op_Inequality var esp = ctx.ESP; var mStack = ctx.ManagedStack; var domain = ctx.AppDomain; var dele1 = StackObject.ToObject((esp - 1 - 1), domain, mStack); var dele2 = StackObject.ToObject((esp - 1), domain, mStack); if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) return !((IDelegateAdapter)dele1).Equals((IDelegateAdapter)dele2); else return !((IDelegateAdapter)dele1).Equals((Delegate)dele2); } else { if (dele2 is IDelegateAdapter) return (Delegate)dele1 != ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType()); else return (Delegate)dele1 != (Delegate)dele2; } } else return dele1 != null; } else return dele2 != null; }*/ public static StackObject* GetTypeFromHandle(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { //Nothing to do return esp; } /*public static object GetTypeFromHandle(ILContext ctx, object instance, object[] param, IType[] genericArguments) { return param[0]; }*/ public unsafe static StackObject* MethodInfoInvoke(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { AppDomain domain = intp.AppDomain; //Don't ask me why not esp - 3, unity won't return the right result var ret = ILIntepreter.Minus(esp, 3); var param = esp - 1; var p = StackObject.ToObject(param, domain, mStack); intp.Free(param); param = esp - 1 - 1; var obj = StackObject.ToObject(param, domain, mStack); intp.Free(param); param = ILIntepreter.Minus(esp, 3); object instance = StackObject.ToObject(param, domain, mStack); intp.Free(param); if (instance is ILRuntimeMethodInfo) { if (obj != null) esp = ILIntepreter.PushObject(ret, mStack, obj); else esp = ret; if (p != null) { object[] arr = (object[])p; foreach (var i in arr) { esp = ILIntepreter.PushObject(esp, mStack, i); } } bool unhandled; var ilmethod = ((ILRuntimeMethodInfo)instance).ILMethod; return intp.Execute(ilmethod, esp, out unhandled); } else return ILIntepreter.PushObject(ret, mStack, ((MethodInfo)instance).Invoke(obj, (object[])p)); } /*public unsafe static object MethodInfoInvoke(ILContext ctx, object instance, object[] param, IType[] genericArguments) { var esp = ctx.ESP; var mStack = ctx.ManagedStack; var domain = ctx.AppDomain; var intp = ctx.Interpreter; //Don't ask me why not esp - 3, unity won't return the right result var obj = param[0]; var p = param[1]; if (instance is ILRuntimeMethodInfo) { if (obj != null) esp = ILIntepreter.PushObject(esp, mStack, obj); if (p != null) { object[] arr = (object[])p; foreach (var i in arr) { esp = ILIntepreter.PushObject(esp, mStack, i); } } bool unhandled; var ilmethod = ((ILRuntimeMethodInfo)instance).ILMethod; esp = intp.Execute(ilmethod, esp, out unhandled); object res = null; if (ilmethod.ReturnType != domain.VoidType) { res = StackObject.ToObject((esp - 1),domain, mStack); intp.Free(esp - 1); } return res; } else return ((MethodInfo)instance).Invoke(obj, (object[])p); }*/ public unsafe static StackObject* ObjectGetType(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { AppDomain domain = intp.AppDomain; var ret = esp - 1; var param = esp - 1; var instance = StackObject.ToObject(param, domain, mStack); intp.Free(param); var type = instance.GetType(); if (type == typeof(ILTypeInstance)) { return ILIntepreter.PushObject(ret, mStack, ((ILTypeInstance)instance).Type.ReflectionType); } else return ILIntepreter.PushObject(ret, mStack, type); } /*public unsafe static object ObjectGetType(ILContext ctx, object instance, object[] param, IType[] genericArguments) { var type = instance.GetType(); if (type == typeof(ILTypeInstance)) { return ((ILTypeInstance)instance).Type.ReflectionType; } else return type; }*/ } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Enviorment/CrossBindingAdaptor.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.Method; using ILRuntime.CLR.TypeSystem; using ILRuntime.Runtime.Intepreter; namespace ILRuntime.Runtime.Enviorment { public interface CrossBindingAdaptorType { ILTypeInstance ILInstance { get; } } /// /// This interface is used for inheritance and implementation of CLR Types or interfaces /// public abstract class CrossBindingAdaptor : IType { IType type; /// /// This returns the CLR type to be inherited or CLR interface to be implemented /// public abstract Type BaseCLRType { get; } /// /// If this Adaptor is capable to impelement multuple interfaces, use this Property, AND BaseCLRType should return null /// public virtual Type[] BaseCLRTypes { get { return null; } } public abstract Type AdaptorType { get; } public abstract object CreateCLRInstance(Enviorment.AppDomain appdomain, ILTypeInstance instance); internal IType RuntimeType { get { return type; } set { type = value; } } #region IType Members public IMethod GetMethod(string name, int paramCount, bool declaredOnly = false) { return type.GetMethod(name, paramCount, declaredOnly); } public IMethod GetMethod(string name, List param, IType[] genericArguments, IType returnType = null, bool declaredOnly = false) { return type.GetMethod(name, param, genericArguments, returnType, declaredOnly); } public List GetMethods() { return type.GetMethods(); } public int GetFieldIndex(object token) { return type.GetFieldIndex(token); } public IMethod GetConstructor(List param) { return type.GetConstructor(param); } public bool CanAssignTo(IType type) { bool res = false; if (BaseType != null) res = BaseType.CanAssignTo(type); var interfaces = Implements; if (!res && interfaces != null) { for (int i = 0; i < interfaces.Length; i++) { var im = interfaces[i]; res = im.CanAssignTo(type); if (res) return true; } } return res; } public IType MakeGenericInstance(KeyValuePair[] genericArguments) { return type.MakeGenericInstance(genericArguments); } public IType MakeByRefType() { return type.MakeByRefType(); } public IType MakeArrayType() { return type.MakeArrayType(); } public IType FindGenericArgument(string key) { return type.FindGenericArgument(key); } public IType ResolveGenericType(IType contextType) { return type.ResolveGenericType(contextType); } public IMethod GetVirtualMethod(IMethod method) { return type.GetVirtualMethod(method); } public bool IsGenericInstance { get { return type.IsGenericInstance; } } public KeyValuePair[] GenericArguments { get { return type.GenericArguments; } } public Type TypeForCLR { get { return type.TypeForCLR; } } public IType ByRefType { get { return type.ByRefType; } } public IType ArrayType { get { return type.ArrayType; } } public string FullName { get { return type.FullName; } } public string Name { get { return type.Name; } } public bool IsValueType { get { return type.IsValueType; } } public bool IsPrimitive { get { return type.IsPrimitive; } } public bool IsDelegate { get { return type.IsDelegate; } } public AppDomain AppDomain { get { return type.AppDomain; } } public Type ReflectionType { get { return type.ReflectionType; } } public IType BaseType { get { return type.BaseType; } } public IType[] Implements { get { return type.Implements; } } public bool HasGenericParameter { get { return type.HasGenericParameter; } } public bool IsArray { get { return false; } } #endregion } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Enviorment/DelegateManager.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.Other; using ILRuntime.Runtime.Intepreter; namespace ILRuntime.Runtime.Enviorment { public class DelegateManager { List methods = new List(); List functions = new List(); IDelegateAdapter zeroParamMethodAdapter = new MethodDelegateAdapter(); IDelegateAdapter dummyAdapter = new DummyDelegateAdapter(); Dictionary> clrDelegates = new Dictionary>(new ByReferenceKeyComparer()); Func defaultConverter; Enviorment.AppDomain appdomain; public DelegateManager(Enviorment.AppDomain appdomain) { this.appdomain = appdomain; defaultConverter = DefaultConverterStub; } static Delegate DefaultConverterStub(Delegate dele) { return dele; } public void RegisterDelegateConvertor(Func action) { var type = typeof(T); if (type.IsSubclassOf(typeof(Delegate))) { clrDelegates[type] = action; } else throw new NotSupportedException(); } public void RegisterMethodDelegate() { DelegateMapNode node = new Enviorment.DelegateManager.DelegateMapNode(); node.Adapter = new MethodDelegateAdapter(); node.ParameterTypes = new Type[] { typeof(T1) }; methods.Add(node); RegisterDelegateConvertor>(defaultConverter); } public void RegisterMethodDelegate() { DelegateMapNode node = new Enviorment.DelegateManager.DelegateMapNode(); node.Adapter = new MethodDelegateAdapter(); node.ParameterTypes = new Type[] { typeof(T1), typeof(T2) }; methods.Add(node); RegisterDelegateConvertor>(defaultConverter); } public void RegisterMethodDelegate() { DelegateMapNode node = new Enviorment.DelegateManager.DelegateMapNode(); node.Adapter = new MethodDelegateAdapter(); node.ParameterTypes = new Type[] { typeof(T1), typeof(T2), typeof(T3) }; methods.Add(node); RegisterDelegateConvertor>(defaultConverter); } public void RegisterMethodDelegate() { DelegateMapNode node = new Enviorment.DelegateManager.DelegateMapNode(); node.Adapter = new MethodDelegateAdapter(); node.ParameterTypes = new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) }; methods.Add(node); RegisterDelegateConvertor>(defaultConverter); } public void RegisterFunctionDelegate() { DelegateMapNode node = new Enviorment.DelegateManager.DelegateMapNode(); node.Adapter = new FunctionDelegateAdapter(); node.ParameterTypes = new Type[] { typeof(TResult) }; functions.Add(node); RegisterDelegateConvertor>(defaultConverter); } public void RegisterFunctionDelegate() { DelegateMapNode node = new Enviorment.DelegateManager.DelegateMapNode(); node.Adapter = new FunctionDelegateAdapter(); node.ParameterTypes = new Type[] { typeof(T1), typeof(TResult) }; functions.Add(node); RegisterDelegateConvertor>(defaultConverter); } public void RegisterFunctionDelegate() { DelegateMapNode node = new Enviorment.DelegateManager.DelegateMapNode(); node.Adapter = new FunctionDelegateAdapter(); node.ParameterTypes = new Type[] { typeof(T1), typeof(T2), typeof(TResult) }; functions.Add(node); RegisterDelegateConvertor>(defaultConverter); } public void RegisterFunctionDelegate() { DelegateMapNode node = new Enviorment.DelegateManager.DelegateMapNode(); node.Adapter = new FunctionDelegateAdapter(); node.ParameterTypes = new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(TResult) }; functions.Add(node); RegisterDelegateConvertor>(defaultConverter); } public void RegisterFunctionDelegate() { DelegateMapNode node = new Enviorment.DelegateManager.DelegateMapNode(); node.Adapter = new FunctionDelegateAdapter(); node.ParameterTypes = new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(TResult) }; functions.Add(node); RegisterDelegateConvertor>(defaultConverter); } internal Delegate ConvertToDelegate(Type clrDelegateType, IDelegateAdapter adapter) { Func func; if(adapter is DummyDelegateAdapter) { DelegateAdapter.ThrowAdapterNotFound(adapter.Method); return null; } if (clrDelegates.TryGetValue(clrDelegateType, out func)) { return func(adapter.Delegate); } else { StringBuilder sb = new StringBuilder(); string clsName, rName; bool isByRef; clrDelegateType.GetClassName(out clsName, out rName, out isByRef); sb.AppendLine("Cannot find convertor for " + rName); sb.AppendLine("Please add following code:"); sb.Append("appdomain.DelegateManager.RegisterDelegateConvertor<"); sb.Append(rName); sb.AppendLine(">((act) =>"); sb.AppendLine("{"); sb.Append(" return new "); sb.Append(rName); sb.Append("(("); var mi = clrDelegateType.GetMethod("Invoke"); bool first = true; foreach(var i in mi.GetParameters()) { if (first) { first = false; } else sb.Append(", "); sb.Append(i.Name); } sb.AppendLine(") =>"); sb.AppendLine(" {"); if(mi.ReturnType != appdomain.VoidType.TypeForCLR) { sb.Append(" return ((Func<"); first = true; foreach (var i in mi.GetParameters()) { if (first) { first = false; } else sb.Append(", "); i.ParameterType.GetClassName(out clsName, out rName, out isByRef); sb.Append(rName); } if (!first) sb.Append(", "); mi.ReturnType.GetClassName(out clsName, out rName, out isByRef); sb.Append(rName); } else { sb.Append(" ((Action<"); first = true; foreach (var i in mi.GetParameters()) { if (first) { first = false; } else sb.Append(", "); i.ParameterType.GetClassName(out clsName, out rName, out isByRef); sb.Append(rName); } } sb.Append(">)act)("); first = true; foreach (var i in mi.GetParameters()) { if (first) { first = false; } else sb.Append(", "); sb.Append(i.Name); } sb.AppendLine(");"); sb.AppendLine(" });"); sb.AppendLine("});"); throw new KeyNotFoundException(sb.ToString()); } } internal IDelegateAdapter FindDelegateAdapter(ILTypeInstance instance, ILMethod method) { IDelegateAdapter res; if (method.ReturnType == appdomain.VoidType) { if (method.ParameterCount == 0) { res = zeroParamMethodAdapter.Instantiate(appdomain, instance, method); if (instance != null) instance.SetDelegateAdapter(method, res); return res; } foreach (var i in methods) { if (i.ParameterTypes.Length == method.ParameterCount) { bool match = true; for (int j = 0; j < method.ParameterCount; j++) { if (i.ParameterTypes[j] != method.Parameters[j].TypeForCLR) { match = false; break; } } if (match) { res = i.Adapter.Instantiate(appdomain, instance, method); if (instance != null) instance.SetDelegateAdapter(method, res); return res; } } } } else { foreach (var i in functions) { if (i.ParameterTypes.Length == method.ParameterCount + 1) { bool match = true; for (int j = 0; j < method.ParameterCount; j++) { if (i.ParameterTypes[j] != method.Parameters[j].TypeForCLR) { match = false; break; } } if (match) { if (method.ReturnType.TypeForCLR == i.ParameterTypes[method.ParameterCount]) { res = i.Adapter.Instantiate(appdomain, instance, method); if (instance != null) instance.SetDelegateAdapter(method, res); return res; } } } } } res = dummyAdapter.Instantiate(appdomain, instance, method); if (instance != null) instance.SetDelegateAdapter(method, res); return res; } class DelegateMapNode { public IDelegateAdapter Adapter { get; set; } public Type[] ParameterTypes { get; set; } } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Enviorment/ILContext.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Stack; using ILRuntime.CLR.Method; namespace ILRuntime.Runtime.Enviorment { public unsafe struct ILContext { public AppDomain AppDomain { get; private set; } public StackObject* ESP { get; private set; } public IList ManagedStack { get; private set; } public IMethod Method { get; private set; } public ILIntepreter Interpreter { get; private set; } internal ILContext(AppDomain domain,ILIntepreter intpreter, StackObject* esp, IList mStack, IMethod method) { AppDomain = domain; ESP = esp; ManagedStack = mStack; Method = method; Interpreter = intpreter; } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Enviorment/ValueTypeBinder.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.Method; using ILRuntime.CLR.TypeSystem; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Stack; namespace ILRuntime.Runtime.Enviorment { public unsafe abstract class ValueTypeBinder { CLRType clrType; Enviorment.AppDomain domain; public CLRType CLRType { get { return clrType; } set { if (clrType == null) { clrType = value; domain = value.AppDomain; } else throw new NotSupportedException(); } } public abstract void CopyValueTypeToStack(object ins, StackObject* ptr, IList mStack); public abstract object ToObject(StackObject* esp, IList managedStack); public virtual void RegisterCLRRedirection(Enviorment.AppDomain appdomain) { } protected void CopyValueTypeToStack(ref K ins, StackObject* esp, IList mStack) where K : struct { switch (esp->ObjectType) { case ObjectTypes.ValueTypeObjectReference: { var dst = *(StackObject**)&esp->Value; var vb = ((CLRType)domain.GetType(dst->Value)).ValueTypeBinder as ValueTypeBinder; if (vb != null) { vb.CopyValueTypeToStack(ref ins, dst, mStack); } else throw new NotSupportedException(); } break; case ObjectTypes.Object: mStack[esp->Value] = ins; break; default: throw new NotImplementedException(); } } protected void AssignFromStack(ref K ins, StackObject* esp, IList mStack) where K : struct { switch (esp->ObjectType) { case ObjectTypes.Null: throw new NullReferenceException(); case ObjectTypes.Object: ins = (K)mStack[esp->Value]; break; case ObjectTypes.ValueTypeObjectReference: { var dst = *(StackObject**)&esp->Value; var vb = ((CLRType)domain.GetType(dst->Value)).ValueTypeBinder as ValueTypeBinder; if (vb != null) { vb.AssignFromStack(ref ins, dst, mStack); } else throw new NotSupportedException(); } break; default: throw new NotImplementedException(); } } } public unsafe abstract class ValueTypeBinder : ValueTypeBinder where T : struct { public override unsafe void CopyValueTypeToStack(object ins, StackObject* ptr, IList mStack) { T obj = (T)ins; CopyValueTypeToStack(ref obj, ptr, mStack); } public abstract void CopyValueTypeToStack(ref T ins, StackObject* ptr, IList mStack); public override unsafe object ToObject(StackObject* esp, IList managedStack) { T obj = new T(); AssignFromStack(ref obj, esp, managedStack); return obj; } public abstract void AssignFromStack(ref T ins, StackObject* ptr, IList mStack); } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Extensions.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.Runtime.Stack; namespace ILRuntime.Runtime { static class Extensions { public static void GetClassName(this Type type, out string clsName, out string realClsName, out bool isByRef, bool simpleClassName = false) { isByRef = type.IsByRef; bool isArray = type.IsArray; if (isByRef) type = type.GetElementType(); if (isArray) type = type.GetElementType(); string realNamespace = null; bool isNestedGeneric = false; if (type.IsNested) { string bClsName, bRealClsName; bool tmp; var rt = type.ReflectedType; if(rt.IsGenericType && rt.IsGenericTypeDefinition) { if (type.IsGenericType) { rt = rt.MakeGenericType(type.GetGenericArguments()); isNestedGeneric = true; } } GetClassName(rt, out bClsName, out bRealClsName, out tmp); clsName = simpleClassName ? "" : bClsName + "_"; realNamespace = bRealClsName + "."; } else { clsName = simpleClassName ? "" : (!string.IsNullOrEmpty(type.Namespace) ? type.Namespace.Replace(".", "_") + "_" : ""); realNamespace = !string.IsNullOrEmpty(type.Namespace) ? type.Namespace + "." : null; } clsName = clsName + type.Name.Replace(".", "_").Replace("`", "_").Replace("<", "_").Replace(">", "_"); bool isGeneric = false; string ga = null; if (type.IsGenericType && !isNestedGeneric) { isGeneric = true; clsName += "_"; ga = "<"; var args = type.GetGenericArguments(); bool first = true; foreach (var j in args) { if (first) first = false; else { clsName += "_"; ga += ", "; } string a, b; bool tmp; GetClassName(j, out a, out b, out tmp, true); clsName += a; ga += b; } ga += ">"; } if (!simpleClassName) clsName += "_Binding"; if (isArray) clsName += "_Array"; realClsName = realNamespace; if (isGeneric) { int idx = type.Name.IndexOf("`"); if (idx > 0) { realClsName += type.Name.Substring(0, idx); realClsName += ga; } else realClsName += type.Name; } else realClsName += type.Name; if (isArray) realClsName += "[]"; } public static int ToInt32(this object obj) { if (obj is int) return (int)obj; if (obj is float) return (int)(float)obj; if (obj is long) return (int)(long)obj; if (obj is short) return (int)(short)obj; if (obj is double) return (int)(double)obj; if (obj is byte) return (int)(byte)obj; if (obj is Intepreter.ILEnumTypeInstance) return (int)((Intepreter.ILEnumTypeInstance)obj)[0]; if (obj is uint) return (int)(uint)obj; if (obj is ushort) return (int)(ushort)obj; if (obj is sbyte) return (int)(sbyte)obj; throw new InvalidCastException(); } public static long ToInt64(this object obj) { if (obj is long) return (long)obj; if (obj is int) return (long)(int)obj; if (obj is float) return (long)(float)obj; if (obj is short) return (long)(short)obj; if (obj is double) return (long)(double)obj; if (obj is byte) return (long)(byte)obj; if (obj is uint) return (long)(uint)obj; if (obj is ushort) return (long)(ushort)obj; if (obj is sbyte) return (long)(sbyte)obj; throw new InvalidCastException(); } public static short ToInt16(this object obj) { if (obj is short) return (short)obj; if (obj is long) return (short)(long)obj; if (obj is int) return (short)(int)obj; if (obj is float) return (short)(float)obj; if (obj is double) return (short)(double)obj; if (obj is byte) return (short)(byte)obj; if (obj is uint) return (short)(uint)obj; if (obj is ushort) return (short)(ushort)obj; if (obj is sbyte) return (short)(sbyte)obj; throw new InvalidCastException(); } public static float ToFloat(this object obj) { if (obj is float) return (float)obj; if (obj is int) return (float)(int)obj; if (obj is long) return (float)(long)obj; if (obj is short) return (float)(short)obj; if (obj is double) return (float)(double)obj; if (obj is byte) return (float)(byte)obj; if (obj is uint) return (float)(uint)obj; if (obj is ushort) return (float)(ushort)obj; if (obj is sbyte) return (float)(sbyte)obj; throw new InvalidCastException(); } public static double ToDouble(this object obj) { if (obj is double) return (double)obj; if (obj is float) return (float)obj; if (obj is int) return (double)(int)obj; if (obj is long) return (double)(long)obj; if (obj is short) return (double)(short)obj; if (obj is byte) return (double)(byte)obj; if (obj is uint) return (double)(uint)obj; if (obj is ushort) return (double)(ushort)obj; if (obj is sbyte) return (double)(sbyte)obj; throw new InvalidCastException(); } public static Type GetActualType(this object value) { if (value is ILRuntime.Runtime.Enviorment.CrossBindingAdaptorType) return ((ILRuntime.Runtime.Enviorment.CrossBindingAdaptorType)value).ILInstance.Type.ReflectionType; if (value is ILRuntime.Runtime.Intepreter.ILTypeInstance) return ((ILRuntime.Runtime.Intepreter.ILTypeInstance)value).Type.ReflectionType; else return value.GetType(); } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Intepreter/DelegateAdapter.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.Runtime; using ILRuntime.Runtime.Stack; using ILRuntime.Other; using ILRuntime.Runtime.Enviorment; namespace ILRuntime.Runtime.Intepreter { #region Functions class FunctionDelegateAdapter : DelegateAdapter { Func action; public FunctionDelegateAdapter() { } private FunctionDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } TResult InvokeILMethod() { if (method.HasThis) return (TResult)appdomain.Invoke(method, instance, null); else return (TResult)appdomain.Invoke(method, null, null); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new FunctionDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new FunctionDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Func)dele; } public override void Remove(Delegate dele) { action -= (Func)dele; } } class FunctionDelegateAdapter : DelegateAdapter { Func action; public FunctionDelegateAdapter() { } private FunctionDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } TResult InvokeILMethod(T1 p1) { if (method.HasThis) return (TResult)appdomain.Invoke(method, instance, p1); else return (TResult)appdomain.Invoke(method, null, p1); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new FunctionDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new FunctionDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Func)dele; } public override void Remove(Delegate dele) { action -= (Func)dele; } } class FunctionDelegateAdapter : DelegateAdapter { Func action; public FunctionDelegateAdapter() { } private FunctionDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } TResult InvokeILMethod(T1 p1, T2 p2) { if (method.HasThis) return (TResult)appdomain.Invoke(method, instance, p1, p2); else return (TResult)appdomain.Invoke(method, null, p1, p2); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new FunctionDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new FunctionDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Func)dele; } public override void Remove(Delegate dele) { action -= (Func)dele; } } class FunctionDelegateAdapter : DelegateAdapter { Func action; public FunctionDelegateAdapter() { } private FunctionDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } TResult InvokeILMethod(T1 p1, T2 p2, T3 p3) { if (method.HasThis) return (TResult)appdomain.Invoke(method, instance, p1, p2, p3); else return (TResult)appdomain.Invoke(method, null, p1, p2, p3); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new FunctionDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new FunctionDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Func)dele; } public override void Remove(Delegate dele) { action -= (Func)dele; } } class FunctionDelegateAdapter : DelegateAdapter { Func action; public FunctionDelegateAdapter() { } private FunctionDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } TResult InvokeILMethod(T1 p1, T2 p2, T3 p3, T4 p4) { if (method.HasThis) return (TResult)appdomain.Invoke(method, instance, p1, p2, p3, p4); else return (TResult)appdomain.Invoke(method, null, p1, p2, p3, p4); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new FunctionDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new FunctionDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Func)dele; } public override void Remove(Delegate dele) { action -= (Func)dele; } } #endregion #region Methods class MethodDelegateAdapter : DelegateAdapter { Action action; public MethodDelegateAdapter() { } private MethodDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } void InvokeILMethod(T1 p1) { if (method.HasThis) appdomain.Invoke(method, instance, p1); else appdomain.Invoke(method, null, p1); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new MethodDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new MethodDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Action)dele; } public override void Remove(Delegate dele) { action -= (Action)dele; } } class MethodDelegateAdapter : DelegateAdapter { Action action; public MethodDelegateAdapter() { } private MethodDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } void InvokeILMethod(T1 p1, T2 p2) { if (method.HasThis) appdomain.Invoke(method, instance, p1, p2); else appdomain.Invoke(method, instance, p1, p2); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new MethodDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new MethodDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Action)dele; } public override void Remove(Delegate dele) { action -= (Action)dele; } } class MethodDelegateAdapter : DelegateAdapter { Action action; public MethodDelegateAdapter() { } private MethodDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } void InvokeILMethod(T1 p1, T2 p2, T3 p3) { if (method.HasThis) appdomain.Invoke(method, instance, p1, p2, p3); else appdomain.Invoke(method, null, p1, p2, p3); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new MethodDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new MethodDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Action)dele; } public override void Remove(Delegate dele) { action -= (Action)dele; } } class MethodDelegateAdapter : DelegateAdapter { Action action; public MethodDelegateAdapter() { } private MethodDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } void InvokeILMethod(T1 p1, T2 p2, T3 p3, T4 p4) { if (method.HasThis) appdomain.Invoke(method, instance, p1, p2, p3, p4); else appdomain.Invoke(method, null, p1, p2, p3, p4); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new MethodDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new MethodDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Action)dele; } public override void Remove(Delegate dele) { action -= (Action)dele; } } class MethodDelegateAdapter : DelegateAdapter { Action action; public MethodDelegateAdapter() { } protected MethodDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } void InvokeILMethod() { if (method.HasThis) appdomain.Invoke(method, instance, null); else appdomain.Invoke(method, null, null); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new MethodDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new MethodDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Action)dele; } public override void Remove(Delegate dele) { action -= (Action)dele; } } class DummyDelegateAdapter : DelegateAdapter { public DummyDelegateAdapter() { } protected DummyDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { } public override Delegate Delegate { get { ThrowAdapterNotFound(method); return null; } } void InvokeILMethod() { if (method.HasThis) appdomain.Invoke(method, instance, null); else appdomain.Invoke(method, null, null); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new DummyDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new DummyDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { ThrowAdapterNotFound(method); } public override void Remove(Delegate dele) { ThrowAdapterNotFound(method); } } #endregion abstract class DelegateAdapter : ILTypeInstance, IDelegateAdapter { protected ILMethod method; protected ILTypeInstance instance; protected Enviorment.AppDomain appdomain; Dictionary converters; IDelegateAdapter next; protected bool isClone; public abstract Delegate Delegate { get; } public IDelegateAdapter Next { get { return next; } } public ILTypeInstance Instance { get { return instance; } } public ILMethod Method { get { return method; } } protected DelegateAdapter() { } protected DelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { this.appdomain = appdomain; this.instance = instance; this.method = method; CLRInstance = this; } public override bool IsValueType { get { return false; } } public unsafe StackObject* ILInvoke(ILIntepreter intp, StackObject* esp, IList mStack) { var ebp = esp; esp = ILInvokeSub(intp, esp, mStack); return ClearStack(intp, esp, ebp, mStack); } unsafe StackObject* ILInvokeSub(ILIntepreter intp, StackObject* esp, IList mStack) { var ebp = esp; bool unhandled; if (method.HasThis) esp = ILIntepreter.PushObject(esp, mStack, instance); int paramCnt = method.ParameterCount; for(int i = paramCnt; i > 0; i--) { intp.CopyToStack(esp, Minus(ebp, i), mStack); esp++; } var ret = intp.Execute(method, esp, out unhandled); if (next != null) { if (method.ReturnType != appdomain.VoidType) { intp.Free(ret - 1);//Return value for multicast delegate doesn't make sense, only return the last one's value } DelegateAdapter n = (DelegateAdapter)next; ret = n.ILInvokeSub(intp, ebp, mStack); } return ret; } unsafe StackObject* ClearStack(ILIntepreter intp, StackObject* esp, StackObject* ebp, IList mStack) { int paramCnt = method.ParameterCount; object retObj = null; StackObject retSObj = StackObject.Null; bool hasReturn = method.ReturnType != appdomain.VoidType; if (hasReturn) { var ret = esp - 1; retSObj = *ret; if(ret->ObjectType>= ObjectTypes.Object) { retObj = mStack[ret->Value]; } intp.Free(ret); } for (int i = 1; i <= paramCnt; i++) { intp.Free(ebp - i); } var returnVal = Minus(ebp, paramCnt + 1); intp.Free(returnVal);//Free delegateInstance if (hasReturn) { *returnVal = retSObj; if(retObj != null) { returnVal->Value = mStack.Count; mStack.Add(retObj); } returnVal++; } return returnVal; } public abstract IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method); public new abstract IDelegateAdapter Clone(); public bool IsClone { get { return isClone; } } public virtual void Combine(IDelegateAdapter adapter) { if (next != null) next.Combine(adapter); else next = adapter; } public abstract void Combine(Delegate dele); public virtual void Remove(IDelegateAdapter adapter) { if (next != null) { if (next.Equals(adapter)) { next = ((DelegateAdapter)next).next; } else next.Remove(adapter); } } public abstract void Remove(Delegate dele); public virtual bool Equals(IDelegateAdapter adapter) { if (adapter is DelegateAdapter) { DelegateAdapter b = (DelegateAdapter)adapter; return instance == b.instance && method == b.method; } else return false; } public virtual bool Equals(Delegate dele) { return Delegate == dele; } public override string ToString() { return method.ToString(); } public Delegate GetConvertor(Type type) { if (converters == null) converters = new Dictionary(new ByReferenceKeyComparer()); Delegate res; if (converters.TryGetValue(type, out res)) return res; else { res = appdomain.DelegateManager.ConvertToDelegate(type, this); converters[type] = res; return res; } } unsafe StackObject* Minus(StackObject* a, int b) { return (StackObject*)((long)a - sizeof(StackObject) * b); } public static void ThrowAdapterNotFound(IMethod method) { StringBuilder sb = new StringBuilder(); sb.Append("Cannot find Delegate Adapter for:"); sb.Append(method.ToString()); string clsName, rName; bool isByRef; if (method.ReturnType.Name != "Void" || method.ParameterCount > 0) { sb.AppendLine(", Please add following code:"); if (method.ReturnType.Name == "Void") { sb.Append("appdomain.DelegateManager.RegisterMethodDelegate<"); bool first = true; foreach(var i in method.Parameters) { if (first) { first = false; } else { sb.Append(", "); } i.TypeForCLR.GetClassName(out clsName, out rName, out isByRef); sb.Append(rName); } sb.AppendLine(">();"); } else { sb.Append("appdomain.DelegateManager.RegisterFunctionDelegate<"); bool first = true; foreach (var i in method.Parameters) { if (first) { first = false; } else { sb.Append(", "); } i.TypeForCLR.GetClassName(out clsName, out rName, out isByRef); sb.Append(rName); } if (!first) sb.Append(", "); method.ReturnType.TypeForCLR.GetClassName(out clsName, out rName, out isByRef); sb.Append(rName); sb.AppendLine(">();"); } } throw new KeyNotFoundException(sb.ToString()); } } unsafe interface IDelegateAdapter { Delegate Delegate { get; } IDelegateAdapter Next { get; } ILTypeInstance Instance { get; } ILMethod Method { get; } StackObject* ILInvoke(ILIntepreter intp, StackObject* esp, IList mStack); IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method); bool IsClone { get; } IDelegateAdapter Clone(); Delegate GetConvertor(Type type); void Combine(IDelegateAdapter adapter); void Combine(Delegate dele); void Remove(IDelegateAdapter adapter); void Remove(Delegate dele); bool Equals(IDelegateAdapter adapter); bool Equals(Delegate dele); } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Intepreter/ILIntepreter.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Stack; using ILRuntime.CLR.Method; using ILRuntime.CLR.TypeSystem; using ILRuntime.Runtime.Intepreter.OpCodes; using ILRuntime.Runtime.Debugger; using ILRuntime.CLR.Utils; using ILRuntime.Other; namespace ILRuntime.Runtime.Intepreter { public unsafe class ILIntepreter { Enviorment.AppDomain domain; RuntimeStack stack; object _lockObj; bool allowUnboundCLRMethod; public RuntimeStack Stack { get { return stack; } } public bool ShouldBreak { get; set; } public StepTypes CurrentStepType { get; set; } public StackObject* LastStepFrameBase { get; set; } public int LastStepInstructionIndex { get; set; } StackObject* ValueTypeBasePointer; public ILIntepreter(Enviorment.AppDomain domain) { this.domain = domain; stack = new RuntimeStack(this); allowUnboundCLRMethod = domain.AllowUnboundCLRMethod; #if DEBUG _lockObj = new object(); #endif } public Enviorment.AppDomain AppDomain { get { return domain; } } public void Break() { //Clear old debug state ClearDebugState(); lock (_lockObj) Monitor.Wait(_lockObj); } public void Resume() { lock (_lockObj) Monitor.Pulse(_lockObj); } public void ClearDebugState() { ShouldBreak = false; CurrentStepType = StepTypes.None; LastStepFrameBase = (StackObject*)0; LastStepInstructionIndex = 0; } public object Run(ILMethod method, object instance, object[] p) { IList mStack = stack.ManagedStack; int mStackBase = mStack.Count; StackObject* esp = stack.StackBase; stack.ResetValueTypePointer(); if (method.HasThis) { if (instance is CrossBindingAdaptorType) instance = ((CrossBindingAdaptorType)instance).ILInstance; if (instance == null) throw new NullReferenceException("instance should not be null!"); esp = PushObject(esp, mStack, instance); } esp = PushParameters(method, esp, p); bool unhandledException; esp = Execute(method, esp, out unhandledException); object result = method.ReturnType != domain.VoidType ? method.ReturnType.TypeForCLR.CheckCLRTypes(StackObject.ToObject((esp - 1), domain, mStack)) : null; //ClearStack #if DEBUG ((List)mStack).RemoveRange(mStackBase, mStack.Count - mStackBase); #else ((UncheckedList)mStack).RemoveRange(mStackBase, mStack.Count - mStackBase); #endif return result; } internal StackObject* Execute(ILMethod method, StackObject* esp, out bool unhandledException) { if (method == null) throw new NullReferenceException(); #if UNITY_EDITOR if (System.Threading.Thread.CurrentThread.ManagedThreadId == AppDomain.UnityMainThreadID) #if UNITY_5_5_OR_NEWER UnityEngine.Profiling.Profiler.BeginSample(method.ToString()); #else UnityEngine.Profiler.BeginSample(method.ToString()); #endif #endif OpCode[] body = method.Body; StackFrame frame; stack.InitializeFrame(method, esp, out frame); StackObject* v1 = frame.LocalVarPointer; StackObject* v2 = frame.LocalVarPointer + 1; StackObject* v3 = frame.LocalVarPointer + 1 + 1; StackObject* v4 = Add(frame.LocalVarPointer, 3); int finallyEndAddress = 0; esp = frame.BasePointer; StackObject* arg = Minus(frame.LocalVarPointer, method.ParameterCount); IList mStack = stack.ManagedStack; int paramCnt = method.ParameterCount; if (method.HasThis)//this parameter is always object reference { arg--; paramCnt++; } unhandledException = false; //Managed Stack reserved for arguments(In case of starg) for (int i = 0; i < paramCnt; i++) { var a = Add(arg, i); switch (a->ObjectType) { case ObjectTypes.Null: //Need to reserve place for null, in case of starg a->ObjectType = ObjectTypes.Object; a->Value = mStack.Count; mStack.Add(null); break; case ObjectTypes.ValueTypeObjectReference: CloneStackValueType(a, a, mStack); break; case ObjectTypes.Object: case ObjectTypes.FieldReference: case ObjectTypes.ArrayReference: frame.ManagedStackBase--; break; } } stack.PushFrame(ref frame); int locBase = mStack.Count; //Managed Stack reserved for local variable for (int i = 0; i < method.LocalVariableCount; i++) { mStack.Add(null); } for (int i = 0; i < method.LocalVariableCount; i++) { var v = method.Variables[i]; if (v.VariableType.IsValueType && !v.VariableType.IsPrimitive) { var t = AppDomain.GetType(v.VariableType, method.DeclearingType, method); if (t is ILType) { //var obj = ((ILType)t).Instantiate(false); var loc = Add(v1, i); stack.AllocValueType(loc, t); /*loc->ObjectType = ObjectTypes.Object; loc->Value = mStack.Count; mStack.Add(obj);*/ } else { CLRType cT = (CLRType)t; var loc = Add(v1, i); if (cT.ValueTypeBinder != null) { stack.AllocValueType(loc, t); } else { var obj = ((CLRType)t).CreateDefaultInstance(); loc->ObjectType = ObjectTypes.Object; loc->Value = locBase + i; mStack[locBase + i] = obj; } } } else { if (v.VariableType.IsPrimitive) { var t = AppDomain.GetType(v.VariableType, method.DeclearingType, method); var loc = Add(v1, i); StackObject.Initialized(loc, t); } else { var loc = Add(v1, i); loc->ObjectType = ObjectTypes.Object; loc->Value = locBase + i; } } } var bp = stack.ValueTypeStackPointer; ValueTypeBasePointer = bp; fixed (OpCode* ptr = body) { OpCode* ip = ptr; OpCodeEnum code = ip->Code; bool returned = false; while (!returned) { try { #if DEBUG if (ShouldBreak) Break(); var insOffset = (int)(ip - ptr); frame.Address.Value = insOffset; AppDomain.DebugService.CheckShouldBreak(method, this, insOffset); #endif code = ip->Code; switch (code) { #region Arguments and Local Variable case OpCodeEnum.Ldarg_0: CopyToStack(esp, arg, mStack); esp++; break; case OpCodeEnum.Ldarg_1: CopyToStack(esp, arg + 1, mStack); esp++; break; case OpCodeEnum.Ldarg_2: CopyToStack(esp, arg + 1 + 1, mStack); esp++; break; case OpCodeEnum.Ldarg_3: CopyToStack(esp, arg + 1 + 1 + 1, mStack); esp++; break; case OpCodeEnum.Ldarg: case OpCodeEnum.Ldarg_S: CopyToStack(esp, Add(arg, ip->TokenInteger), mStack); esp++; break; case OpCodeEnum.Ldarga: case OpCodeEnum.Ldarga_S: { var a = Add(arg, ip->TokenInteger); esp->ObjectType = ObjectTypes.StackObjectReference; *(StackObject**)&esp->Value = a; esp++; } break; case OpCodeEnum.Starg: case OpCodeEnum.Starg_S: { var a = Add(arg, ip->TokenInteger); var val = esp - 1; int idx = a->Value; bool isObj = a->ObjectType >= ObjectTypes.Object; if (val->ObjectType >= ObjectTypes.Object) { a->ObjectType = val->ObjectType; mStack[a->Value] = mStack[val->Value]; a->ValueLow = val->ValueLow; } else { *a = *val; if (isObj) { a->Value = idx; if (val->ObjectType == ObjectTypes.Null) { mStack[a->Value] = null; } } } Free(val); esp--; } break; case OpCodeEnum.Stloc_0: { esp--; int idx = locBase; StLocSub(esp, v1, bp, idx, mStack); } break; case OpCodeEnum.Ldloc_0: CopyToStack(esp, v1, mStack); esp++; break; case OpCodeEnum.Stloc_1: { esp--; int idx = locBase + 1; StLocSub(esp, v2, bp, idx, mStack); } break; case OpCodeEnum.Ldloc_1: CopyToStack(esp, v2, mStack); esp++; break; case OpCodeEnum.Stloc_2: { esp--; int idx = locBase + 2; StLocSub(esp, v3, bp, idx, mStack); break; } case OpCodeEnum.Ldloc_2: CopyToStack(esp, v3, mStack); esp++; break; case OpCodeEnum.Stloc_3: { esp--; int idx = locBase + 3; StLocSub(esp, v4, bp, idx, mStack); } break; case OpCodeEnum.Ldloc_3: CopyToStack(esp, v4, mStack); esp++; break; case OpCodeEnum.Stloc: case OpCodeEnum.Stloc_S: { esp--; var v = Add(frame.LocalVarPointer, ip->TokenInteger); int idx = locBase + ip->TokenInteger; StLocSub(esp, v, bp, idx, mStack); } break; case OpCodeEnum.Ldloc: case OpCodeEnum.Ldloc_S: { var v = Add(frame.LocalVarPointer, ip->TokenInteger); CopyToStack(esp, v, mStack); esp++; } break; case OpCodeEnum.Ldloca: case OpCodeEnum.Ldloca_S: { var v = Add(frame.LocalVarPointer, ip->TokenInteger); esp->ObjectType = ObjectTypes.StackObjectReference; *(StackObject**)&esp->Value = v; esp++; } break; case OpCodeEnum.Ldobj: { var objRef = esp - 1; switch (objRef->ObjectType) { case ObjectTypes.ArrayReference: { var t = AppDomain.GetType(ip->TokenInteger); var obj = mStack[objRef->Value]; var idx = objRef->ValueLow; Free(objRef); LoadFromArrayReference(obj, idx, objRef, t, mStack); } break; case ObjectTypes.StackObjectReference: { var obj = GetObjectAndResolveReference(objRef); *objRef = *obj; if (objRef->ObjectType >= ObjectTypes.Object) { objRef->Value = mStack.Count; mStack.Add(mStack[obj->Value]); } } break; case ObjectTypes.FieldReference: { var obj = mStack[objRef->Value]; int idx = objRef->ValueLow; Free(objRef); if (obj is ILTypeInstance) { ((ILTypeInstance)obj).PushToStack(idx, objRef, AppDomain, mStack); } else { var t = AppDomain.GetType(ip->TokenInteger); obj = ((CLRType) t).GetFieldValue(idx, obj); PushObject(objRef, mStack, obj); } } break; case ObjectTypes.StaticFieldReference: { var t = AppDomain.GetType(objRef->Value); int idx = objRef->ValueLow; Free(objRef); if (t is ILType) { ((ILType)t).StaticInstance.PushToStack(idx, objRef, AppDomain, mStack); } else { var obj = ((CLRType)t).GetFieldValue(idx, null); PushObject(objRef, mStack, obj); } } break; default: throw new NotImplementedException(); } } break; case OpCodeEnum.Stobj: { var objRef = esp - 1 - 1; var val = esp - 1; switch (objRef->ObjectType) { case ObjectTypes.ArrayReference: { var t = AppDomain.GetType(ip->TokenInteger); StoreValueToArrayReference(objRef, val, t, mStack); } break; case ObjectTypes.StackObjectReference: { objRef = GetObjectAndResolveReference(objRef); if (val->ObjectType >= ObjectTypes.Object) { mStack[objRef->Value] = mStack[val->Value]; objRef->ValueLow = val->ValueLow; } else { *objRef = *val; } } break; case ObjectTypes.FieldReference: { var obj = mStack[objRef->Value]; int idx = objRef->ValueLow; if (obj is ILTypeInstance) { ((ILTypeInstance)obj).AssignFromStack(idx, val, AppDomain, mStack); } else { var t = AppDomain.GetType(ip->TokenInteger); ((CLRType)t).SetFieldValue(idx, ref obj, t.TypeForCLR.CheckCLRTypes(StackObject.ToObject(val, AppDomain, mStack))); } } break; case ObjectTypes.StaticFieldReference: { var t = AppDomain.GetType(objRef->Value); if (t is ILType) { ((ILType)t).StaticInstance.AssignFromStack(objRef->ValueLow, val, AppDomain, mStack); } else { ((CLRType)t).SetStaticFieldValue(objRef->ValueLow, t.TypeForCLR.CheckCLRTypes(StackObject.ToObject(val, AppDomain, mStack))); } } break; default: throw new NotImplementedException(); } Free(esp - 1); Free(esp - 1 - 1); esp = esp - 1 - 1; } break; #endregion #region Load Constants case OpCodeEnum.Ldc_I4_M1: esp->Value = -1; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4_0: esp->Value = 0; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4_1: esp->Value = 1; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4_2: esp->Value = 2; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4_3: esp->Value = 3; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4_4: esp->Value = 4; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4_5: esp->Value = 5; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4_6: esp->Value = 6; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4_7: esp->Value = 7; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4_8: esp->Value = 8; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4: case OpCodeEnum.Ldc_I4_S: esp->Value = ip->TokenInteger; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I8: { *(long*)(&esp->Value) = ip->TokenLong; esp->ObjectType = ObjectTypes.Long; esp++; } break; case OpCodeEnum.Ldc_R4: { *(float*)(&esp->Value) = *(float*)&ip->TokenInteger; esp->ObjectType = ObjectTypes.Float; esp++; } break; case OpCodeEnum.Ldc_R8: { *(double*)(&esp->Value) = *(double*)&ip->TokenLong; esp->ObjectType = ObjectTypes.Double; esp++; } break; case OpCodeEnum.Ldnull: { esp = PushNull(esp); } break; case OpCodeEnum.Ldind_I: case OpCodeEnum.Ldind_I1: case OpCodeEnum.Ldind_I2: case OpCodeEnum.Ldind_I4: case OpCodeEnum.Ldind_U1: case OpCodeEnum.Ldind_U2: case OpCodeEnum.Ldind_U4: { var val = GetObjectAndResolveReference(esp - 1); var dst = esp - 1; switch (val->ObjectType) { case ObjectTypes.FieldReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromFieldReference(instance, idx, dst, mStack); } break; case ObjectTypes.ArrayReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromArrayReference(instance, idx, dst, instance.GetType().GetElementType(), mStack); } break; default: { dst->ObjectType = ObjectTypes.Integer; dst->Value = val->Value; dst->ValueLow = 0; } break; } } break; case OpCodeEnum.Ldind_I8: { var val = GetObjectAndResolveReference(esp - 1); var dst = esp - 1; switch (val->ObjectType) { case ObjectTypes.FieldReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromFieldReference(instance, idx, dst, mStack); } break; case ObjectTypes.ArrayReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromArrayReference(instance, idx, dst, instance.GetType().GetElementType(), mStack); } break; default: { *dst = *val; dst->ObjectType = ObjectTypes.Long; dst->ValueLow = 0; } break; } } break; case OpCodeEnum.Ldind_R4: { var val = GetObjectAndResolveReference(esp - 1); var dst = esp - 1; switch (val->ObjectType) { case ObjectTypes.FieldReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromFieldReference(instance, idx, dst, mStack); } break; case ObjectTypes.ArrayReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromArrayReference(instance, idx, dst, instance.GetType().GetElementType(), mStack); } break; default: { dst->ObjectType = ObjectTypes.Float; dst->Value = val->Value; dst->ValueLow = 0; } break; } } break; case OpCodeEnum.Ldind_R8: { var val = GetObjectAndResolveReference(esp - 1); var dst = esp - 1; switch (val->ObjectType) { case ObjectTypes.FieldReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromFieldReference(instance, idx, dst, mStack); } break; case ObjectTypes.ArrayReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromArrayReference(instance, idx, dst, instance.GetType().GetElementType(), mStack); } break; default: { *dst = *val; dst->ObjectType = ObjectTypes.Double; } break; } } break; case OpCodeEnum.Ldind_Ref: { var val = GetObjectAndResolveReference(esp - 1); var dst = esp - 1; switch (val->ObjectType) { case ObjectTypes.FieldReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromFieldReference(instance, idx, dst, mStack); } break; case ObjectTypes.ArrayReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromArrayReference(instance, idx, dst, instance.GetType().GetElementType(), mStack); } break; default: { dst->ObjectType = ObjectTypes.Object; dst->Value = mStack.Count; mStack.Add(mStack[val->Value]); } break; } } break; case OpCodeEnum.Stind_I: case OpCodeEnum.Stind_I1: case OpCodeEnum.Stind_I2: case OpCodeEnum.Stind_I4: case OpCodeEnum.Stind_R4: { var dst = GetObjectAndResolveReference(esp - 1 - 1); var val = esp - 1; switch (dst->ObjectType) { case ObjectTypes.FieldReference: { StoreValueToFieldReference(mStack[dst->Value], dst->ValueLow, val, mStack); } break; case ObjectTypes.ArrayReference: { StoreValueToArrayReference(dst, val, mStack[dst->Value].GetType().GetElementType(), mStack); } break; default: { dst->Value = val->Value; } break; } Free(esp - 1); Free(esp - 1 - 1); esp = esp - 1 - 1; } break; case OpCodeEnum.Stind_I8: case OpCodeEnum.Stind_R8: { var dst = GetObjectAndResolveReference(esp - 1 - 1); var val = esp - 1; switch (dst->ObjectType) { case ObjectTypes.FieldReference: { StoreValueToFieldReference(mStack[dst->Value], dst->ValueLow, val, mStack); } break; default: { dst->Value = val->Value; dst->ValueLow = val->ValueLow; } break; } Free(esp - 1); Free(esp - 1 - 1); esp = esp - 1 - 1; } break; case OpCodeEnum.Stind_Ref: { var dst = GetObjectAndResolveReference(esp - 1 - 1); var val = esp - 1; switch (dst->ObjectType) { case ObjectTypes.FieldReference: { StoreValueToFieldReference(mStack[dst->Value], dst->ValueLow, val, mStack); } break; default: { switch (val->ObjectType) { case ObjectTypes.Object: mStack[dst->Value] = mStack[val->Value]; break; case ObjectTypes.Null: mStack[dst->Value] = null; break; default: throw new NotImplementedException(); } } break; } Free(esp - 1); Free(esp - 1 - 1); esp = esp - 1 - 1; } break; case OpCodeEnum.Ldstr: esp = PushObject(esp, mStack, AppDomain.GetString(ip->TokenLong)); break; #endregion #region Althemetics case OpCodeEnum.Add: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) + *((long*)&b->Value); break; case ObjectTypes.Integer: esp->Value = a->Value + b->Value; break; case ObjectTypes.Float: *((float*)&esp->Value) = *((float*)&a->Value) + *((float*)&b->Value); break; case ObjectTypes.Double: *((double*)&esp->Value) = *((double*)&a->Value) + *((double*)&b->Value); break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Sub: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) - *((long*)&b->Value); break; case ObjectTypes.Integer: esp->Value = a->Value - b->Value; break; case ObjectTypes.Float: *((float*)&esp->Value) = *((float*)&a->Value) - *((float*)&b->Value); break; case ObjectTypes.Double: *((double*)&esp->Value) = *((double*)&a->Value) - *((double*)&b->Value); break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Mul: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) * *((long*)&b->Value); break; case ObjectTypes.Integer: esp->Value = a->Value * b->Value; break; case ObjectTypes.Float: *((float*)&esp->Value) = *((float*)&a->Value) * *((float*)&b->Value); break; case ObjectTypes.Double: *((double*)&esp->Value) = *((double*)&a->Value) * *((double*)&b->Value); break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Div: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) / *((long*)&b->Value); break; case ObjectTypes.Integer: esp->Value = a->Value / b->Value; break; case ObjectTypes.Float: *((float*)&esp->Value) = *((float*)&a->Value) / *((float*)&b->Value); break; case ObjectTypes.Double: *((double*)&esp->Value) = *((double*)&a->Value) / *((double*)&b->Value); break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Div_Un: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((ulong*)&esp->Value) = *((ulong*)&a->Value) / *((ulong*)&b->Value); break; case ObjectTypes.Integer: esp->Value = (int)((uint)a->Value / (uint)b->Value); break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Rem: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) % *((long*)&b->Value); break; case ObjectTypes.Integer: esp->Value = a->Value % b->Value; break; case ObjectTypes.Float: *(float*)&esp->Value = *(float*)&a->Value % *(float*)&b->Value; break; case ObjectTypes.Double: *(double*)&esp->Value = *(double*)&a->Value % *(double*)&b->Value; break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Rem_Un: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((ulong*)&esp->Value) = *((ulong*)&a->Value) % *((ulong*)&b->Value); break; case ObjectTypes.Integer: esp->Value = (int)((uint)a->Value % (uint)b->Value); break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Xor: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) ^ *((long*)&b->Value); break; case ObjectTypes.Integer: esp->Value = a->Value ^ b->Value; break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.And: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) & *((long*)&b->Value); break; case ObjectTypes.Integer: esp->Value = a->Value & b->Value; break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Or: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) | *((long*)&b->Value); break; case ObjectTypes.Integer: esp->Value = a->Value | b->Value; break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Shl: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; int bits = b->Value; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) << bits; break; case ObjectTypes.Integer: esp->Value = a->Value << bits; break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Shr: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; int bits = b->Value; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) >> bits; break; case ObjectTypes.Integer: esp->Value = a->Value >> bits; break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Shr_Un: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; int bits = b->Value; switch (a->ObjectType) { case ObjectTypes.Long: *((ulong*)&esp->Value) = *((ulong*)&a->Value) >> bits; break; case ObjectTypes.Integer: *(uint*)&esp->Value = (uint)a->Value >> bits; break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Not: { StackObject* a = esp - 1; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&a->Value) = ~*((long*)&a->Value); break; case ObjectTypes.Integer: a->Value = ~a->Value; break; default: throw new NotImplementedException(); } } break; case OpCodeEnum.Neg: { StackObject* a = esp - 1; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&a->Value) = -*((long*)&a->Value); break; case ObjectTypes.Integer: a->Value = -a->Value; break; case ObjectTypes.Float: *((float*)&a->Value) = -*((float*)&a->Value); break; case ObjectTypes.Double: *((double*)&a->Value) = -*((double*)&a->Value); break; default: throw new NotImplementedException(); } } break; #endregion #region Control Flows case OpCodeEnum.Ret: returned = true; break; case OpCodeEnum.Brtrue: case OpCodeEnum.Brtrue_S: { esp--; bool res = false; switch (esp->ObjectType) { case ObjectTypes.Integer: res = esp->Value != 0; break; case ObjectTypes.Long: res = *(long*)&esp->Value != 0; break; case ObjectTypes.Object: res = mStack[esp->Value] != null; break; } if (res) { ip = ptr + ip->TokenInteger; Free(esp); continue; } else Free(esp); } break; case OpCodeEnum.Brfalse: case OpCodeEnum.Brfalse_S: { esp--; bool res = false; switch (esp->ObjectType) { case ObjectTypes.Null: res = true; break; case ObjectTypes.Integer: res = esp->Value == 0; break; case ObjectTypes.Long: res = *(long*)&esp->Value == 0; break; case ObjectTypes.Object: res = mStack[esp->Value] == null; Free(esp); break; default: Free(esp); break; } if (res) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Beq: case OpCodeEnum.Beq_S: { var b = esp - 1; var a = esp - 1 - 1; bool transfer = false; if (a->ObjectType == b->ObjectType) { switch (a->ObjectType) { case ObjectTypes.Null: transfer = true; break; case ObjectTypes.Integer: transfer = a->Value == b->Value; break; case ObjectTypes.Long: transfer = *(long*)&a->Value == *(long*)&b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value == *(float*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value == *(double*)&b->Value; break; case ObjectTypes.Object: transfer = mStack[a->Value] == mStack[b->Value]; break; default: throw new NotImplementedException(); } } Free(esp - 1); Free(esp - 1 - 1); esp = esp - 1 - 1; if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Bne_Un: case OpCodeEnum.Bne_Un_S: { var b = esp - 1; var a = esp - 1 - 1; bool transfer = false; if (a->ObjectType == b->ObjectType) { switch (a->ObjectType) { case ObjectTypes.Null: transfer = false; break; case ObjectTypes.Integer: transfer = (uint)a->Value != (uint)b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value != *(float*)&b->Value; break; case ObjectTypes.Long: transfer = *(long*)&a->Value != *(long*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value != *(double*)&b->Value; break; case ObjectTypes.Object: transfer = mStack[a->Value] != mStack[b->Value]; break; default: throw new NotImplementedException(); } } else transfer = true; Free(esp - 1); Free(esp - 1 - 1); esp = esp - 1 - 1; if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Bgt: case OpCodeEnum.Bgt_S: { var b = esp - 1; var a = esp - 1 - 1; esp = esp - 1 - 1; bool transfer = false; switch (esp->ObjectType) { case ObjectTypes.Integer: transfer = a->Value > b->Value; break; case ObjectTypes.Long: transfer = *(long*)&a->Value > *(long*)&b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value > *(float*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value > *(double*)&b->Value; break; default: throw new NotImplementedException(); } if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Bgt_Un: case OpCodeEnum.Bgt_Un_S: { var b = esp - 1; var a = esp - 1 - 1; esp = esp - 1 - 1; bool transfer = false; switch (esp->ObjectType) { case ObjectTypes.Integer: transfer = (uint)a->Value > (uint)b->Value; break; case ObjectTypes.Long: transfer = *(ulong*)&a->Value > *(ulong*)&b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value > *(float*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value > *(double*)&b->Value; break; default: throw new NotImplementedException(); } if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Bge: case OpCodeEnum.Bge_S: { var b = esp - 1; var a = esp - 1 - 1; esp = esp - 1 - 1; bool transfer = false; switch (esp->ObjectType) { case ObjectTypes.Integer: transfer = a->Value >= b->Value; break; case ObjectTypes.Long: transfer = *(long*)&a->Value >= *(long*)&b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value >= *(float*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value >= *(double*)&b->Value; break; default: throw new NotImplementedException(); } if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Bge_Un: case OpCodeEnum.Bge_Un_S: { var b = esp - 1; var a = esp - 1 - 1; esp = esp - 1 - 1; bool transfer = false; switch (esp->ObjectType) { case ObjectTypes.Integer: transfer = (uint)a->Value >= (uint)b->Value; break; case ObjectTypes.Long: transfer = *(ulong*)&a->Value >= *(ulong*)&b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value >= *(float*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value >= *(double*)&b->Value; break; default: throw new NotImplementedException(); } if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Blt: case OpCodeEnum.Blt_S: { var b = esp - 1; var a = esp - 1 - 1; esp = esp - 1 - 1; bool transfer = false; switch (esp->ObjectType) { case ObjectTypes.Integer: transfer = a->Value < b->Value; break; case ObjectTypes.Long: transfer = *(long*)&a->Value < *(long*)&b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value < *(float*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value < *(double*)&b->Value; break; default: throw new NotImplementedException(); } if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Blt_Un: case OpCodeEnum.Blt_Un_S: { var b = esp - 1; var a = esp - 1 - 1; esp = esp - 1 - 1; bool transfer = false; switch (esp->ObjectType) { case ObjectTypes.Integer: transfer = (uint)a->Value < (uint)b->Value; break; case ObjectTypes.Long: transfer = *(ulong*)&a->Value < *(ulong*)&b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value < *(float*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value < *(double*)&b->Value; break; default: throw new NotImplementedException(); } if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Ble: case OpCodeEnum.Ble_S: { var b = esp - 1; var a = esp - 1 - 1; esp = esp - 1 - 1; bool transfer = false; switch (esp->ObjectType) { case ObjectTypes.Integer: transfer = a->Value <= b->Value; break; case ObjectTypes.Long: transfer = *(long*)&a->Value <= *(long*)&b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value <= *(float*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value <= *(double*)&b->Value; break; default: throw new NotImplementedException(); } if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Ble_Un: case OpCodeEnum.Ble_Un_S: { var b = esp - 1; var a = esp - 1 - 1; esp = esp - 1 - 1; bool transfer = false; switch (esp->ObjectType) { case ObjectTypes.Integer: transfer = (uint)a->Value <= (uint)b->Value; break; case ObjectTypes.Long: transfer = *(ulong*)&a->Value <= *(ulong*)&b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value <= *(float*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value <= *(double*)&b->Value; break; default: throw new NotImplementedException(); } if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Br_S: case OpCodeEnum.Br: ip = ptr + ip->TokenInteger; continue; case OpCodeEnum.Switch: { var val = (esp - 1)->Value; Free(esp - 1); esp--; var table = method.JumpTables[ip->TokenInteger]; if (val >= 0 && val < table.Length) { ip = ptr + table[val]; continue; } } break; case OpCodeEnum.Leave: case OpCodeEnum.Leave_S: { if (method.ExceptionHandler != null) { ExceptionHandler eh = null; int addr = ip->TokenInteger; var sql = from e in method.ExceptionHandler where addr == e.HandlerEnd + 1 && e.HandlerType == ExceptionHandlerType.Finally || e.HandlerType == ExceptionHandlerType.Fault select e; eh = sql.FirstOrDefault(); if (eh != null) { finallyEndAddress = ip->TokenInteger; ip = ptr + eh.HandlerStart; continue; } } ip = ptr + ip->TokenInteger; continue; } case OpCodeEnum.Endfinally: { ip = ptr + finallyEndAddress; finallyEndAddress = 0; continue; } case OpCodeEnum.Call: case OpCodeEnum.Callvirt: { IMethod m = domain.GetMethod(ip->TokenInteger); if (m == null) { //Irrelevant method int cnt = (int)ip->TokenLong; //Balance the stack for (int i = 0; i < cnt; i++) { Free(esp - 1); esp--; } } else { if (m is ILMethod) { ILMethod ilm = (ILMethod)m; bool processed = false; if (m.IsDelegateInvoke) { var instance = StackObject.ToObject((Minus(esp, m.ParameterCount + 1)), domain, mStack); if (instance is IDelegateAdapter) { esp = ((IDelegateAdapter)instance).ILInvoke(this, esp, mStack); processed = true; } } if (!processed) { if (code == OpCodeEnum.Callvirt) { var objRef = GetObjectAndResolveReference(Minus(esp, ilm.ParameterCount + 1)); if (objRef->ObjectType == ObjectTypes.Null) throw new NullReferenceException(); var obj = mStack[objRef->Value]; if (obj == null) throw new NullReferenceException(); ilm = ((ILTypeInstance)obj).Type.GetVirtualMethod(ilm) as ILMethod; } esp = Execute(ilm, esp, out unhandledException); ValueTypeBasePointer = bp; if (unhandledException) returned = true; } } else { CLRMethod cm = (CLRMethod)m; bool processed = false; if (cm.IsDelegateInvoke) { var instance = StackObject.ToObject((Minus(esp, cm.ParameterCount + 1)), domain, mStack); if (instance is IDelegateAdapter) { esp = ((IDelegateAdapter)instance).ILInvoke(this, esp, mStack); processed = true; } } if (!processed) { var redirect = cm.Redirection; if (redirect != null) esp = redirect(this, esp, mStack, cm, false); else { #if DEBUG if (!allowUnboundCLRMethod) throw new NotSupportedException(cm.ToString() + " is not bound!"); #endif #if UNITY_EDITOR if (System.Threading.Thread.CurrentThread.ManagedThreadId == AppDomain.UnityMainThreadID) #if UNITY_5_5_OR_NEWER UnityEngine.Profiling.Profiler.BeginSample(cm.ToString()); #else UnityEngine.Profiler.BeginSample(cm.ToString()); #endif #endif object result = cm.Invoke(this, esp, mStack); #if UNITY_EDITOR if (System.Threading.Thread.CurrentThread.ManagedThreadId == AppDomain.UnityMainThreadID) #if UNITY_5_5_OR_NEWER UnityEngine.Profiling.Profiler.EndSample(); #else UnityEngine.Profiler.EndSample(); #endif #endif if (result is CrossBindingAdaptorType) result = ((CrossBindingAdaptorType)result).ILInstance; int paramCount = cm.ParameterCount; for (int i = 1; i <= paramCount; i++) { Free(Minus(esp, i)); } esp = Minus(esp, paramCount); if (cm.HasThis) { Free(esp - 1); esp--; } if (cm.ReturnType != AppDomain.VoidType && !cm.IsConstructor) { esp = PushObject(esp, mStack, result, cm.ReturnType.TypeForCLR == typeof(object)); } } } } } } break; #endregion #region FieldOperation case OpCodeEnum.Stfld: { var objRef = GetObjectAndResolveReference(esp - 1 - 1); if (objRef->ObjectType == ObjectTypes.ValueTypeObjectReference) { StackObject* dst = *(StackObject**)&objRef->Value; var ft = domain.GetType(dst->Value); if (ft is ILType) CopyToValueTypeField(dst, (int)ip->TokenLong, esp - 1, mStack); else CopyToValueTypeField(dst, ((CLRType)ft).FieldIndexMapping[(int)ip->TokenLong], esp - 1, mStack); } else { object obj = RetriveObject(objRef, mStack); if (obj != null) { if (obj is ILTypeInstance) { ILTypeInstance instance = obj as ILTypeInstance; StackObject* val = esp - 1; instance.AssignFromStack((int)ip->TokenLong, val, AppDomain, mStack); } else { var t = obj.GetType(); var type = AppDomain.GetType((int)(ip->TokenLong >> 32)); if (type != null) { var val = esp - 1; var fieldToken = (int)ip->TokenLong; var f = ((CLRType)type).GetField(fieldToken); ((CLRType)type).SetFieldValue(fieldToken, ref obj, f.FieldType.CheckCLRTypes(CheckAndCloneValueType(StackObject.ToObject(val, domain, mStack), domain))); //Writeback if (t.IsValueType) { switch (objRef->ObjectType) { case ObjectTypes.Object: break; case ObjectTypes.FieldReference: { var oldObj = mStack[objRef->Value]; int idx = objRef->ValueLow; if (oldObj is ILTypeInstance) { ((ILTypeInstance)oldObj)[idx] = obj; } else { var it = AppDomain.GetType(oldObj.GetType()); ((CLRType)it).SetFieldValue(idx, ref oldObj, obj); } } break; case ObjectTypes.StaticFieldReference: { var it = AppDomain.GetType(objRef->Value); int idx = objRef->ValueLow; if (it is ILType) { ((ILType)it).StaticInstance[idx] = obj; } else { ((CLRType)it).SetStaticFieldValue(idx, obj); } } break; default: throw new NotImplementedException(); } } } else throw new TypeLoadException(); } } else throw new NullReferenceException(); } Free(esp - 1); Free(esp - 1 - 1); esp = esp - 1 - 1; } break; case OpCodeEnum.Ldfld: { StackObject* objRef = GetObjectAndResolveReference(esp - 1); if (objRef->ObjectType == ObjectTypes.ValueTypeObjectReference) { var dst = *(StackObject**)&objRef->Value; var ft = domain.GetType(dst->Value); if (ft is ILType) dst = Minus(dst, (int)ip->TokenLong + 1); else dst = Minus(dst, ((CLRType)ft).FieldIndexMapping[(int)ip->TokenLong] + 1); CopyToStack(objRef, dst, mStack); } else { object obj = RetriveObject(objRef, mStack); Free(esp - 1); if (obj != null) { if (obj is ILTypeInstance) { ILTypeInstance instance = obj as ILTypeInstance; instance.PushToStack((int)ip->TokenLong, esp - 1, AppDomain, mStack); } else { //var t = obj.GetType(); var type = AppDomain.GetType((int)(ip->TokenLong >> 32)); if (type != null) { var token = (int)ip->TokenLong; var ft = ((CLRType)type).GetField(token); var val = ((CLRType)type).GetFieldValue(token, obj); if (val is CrossBindingAdaptorType) val = ((CrossBindingAdaptorType)val).ILInstance; PushObject(esp - 1, mStack, val, ft.FieldType == typeof(object)); } else throw new TypeLoadException(); } } else throw new NullReferenceException(); } } break; case OpCodeEnum.Ldflda: { StackObject* objRef = GetObjectAndResolveReference(esp - 1); if (objRef->ObjectType == ObjectTypes.ValueTypeObjectReference) { var dst = esp - 1; var ft = domain.GetType((int)(ip->TokenLong >> 32)); StackObject* fieldAddr; if (ft is ILType) { fieldAddr = Minus(*(StackObject**)&objRef->Value, (int)ip->TokenLong + 1); } else { fieldAddr = Minus(*(StackObject**)&objRef->Value, ((CLRType)ft).FieldIndexMapping[(int)ip->TokenLong] + 1); } dst->ObjectType = ObjectTypes.StackObjectReference; *(StackObject**)&dst->Value = fieldAddr; } else { object obj = RetriveObject(objRef, mStack); Free(esp - 1); if (obj != null) { if (obj is ILTypeInstance) { ILTypeInstance instance = obj as ILTypeInstance; instance.PushFieldAddress((int)ip->TokenLong, esp - 1, mStack); } else { objRef = esp - 1; objRef->ObjectType = ObjectTypes.FieldReference; objRef->Value = mStack.Count; mStack.Add(obj); objRef->ValueLow = (int)ip->TokenLong; } } else throw new NullReferenceException(); } } break; case OpCodeEnum.Stsfld: { IType type = AppDomain.GetType((int)(ip->TokenLong >> 32)); if (type != null) { if (type is ILType) { ILType t = type as ILType; StackObject* val = esp - 1; t.StaticInstance.AssignFromStack((int)ip->TokenLong, val, AppDomain, mStack); } else { CLRType t = type as CLRType; int idx = (int)ip->TokenLong; var f = t.GetField(idx); StackObject* val = esp - 1; t.SetStaticFieldValue(idx, f.FieldType.CheckCLRTypes(CheckAndCloneValueType(StackObject.ToObject(val, domain, mStack), domain))); } } else throw new TypeLoadException(); Free(esp - 1); esp -= 1; } break; case OpCodeEnum.Ldsfld: { IType type = AppDomain.GetType((int)(ip->TokenLong >> 32)); if (type != null) { if (type is ILType) { ILType t = type as ILType; t.StaticInstance.PushToStack((int)ip->TokenLong, esp, AppDomain, mStack); } else { CLRType t = type as CLRType; int idx = (int)ip->TokenLong; var f = t.GetField(idx); var val = t.GetFieldValue(idx, null); if (val is CrossBindingAdaptorType) val = ((CrossBindingAdaptorType)val).ILInstance; PushObject(esp, mStack, val, f.FieldType == typeof(object)); } } else throw new TypeLoadException(); esp++; } break; case OpCodeEnum.Ldsflda: { int type = (int)(ip->TokenLong >> 32); int fieldIdx = (int)(ip->TokenLong); esp->ObjectType = ObjectTypes.StaticFieldReference; esp->Value = type; esp->ValueLow = fieldIdx; esp++; } break; case OpCodeEnum.Ldtoken: { switch (ip->TokenInteger) { case 0: { IType type = AppDomain.GetType((int)(ip->TokenLong >> 32)); if (type != null) { if (type is ILType) { ILType t = type as ILType; t.StaticInstance.PushToStack((int)ip->TokenLong, esp, AppDomain, mStack); } else throw new NotImplementedException(); } } esp++; break; case 1: { IType type = AppDomain.GetType((int)ip->TokenLong); if (type != null) { esp = PushObject(esp, mStack, type.ReflectionType); } else throw new TypeLoadException(); } break; default: throw new NotImplementedException(); } } break; case OpCodeEnum.Ldftn: { IMethod m = domain.GetMethod(ip->TokenInteger); esp = PushObject(esp, mStack, m); } break; case OpCodeEnum.Ldvirtftn: { IMethod m = domain.GetMethod(ip->TokenInteger); var objRef = esp - 1; if (m is ILMethod) { ILMethod ilm = (ILMethod)m; var obj = mStack[objRef->Value]; m = ((ILTypeInstance)obj).Type.GetVirtualMethod(ilm) as ILMethod; } else { var obj = mStack[objRef->Value]; if (obj is ILTypeInstance) m = ((ILTypeInstance)obj).Type.GetVirtualMethod(m); else if (obj is CrossBindingAdaptorType) { m = ((CrossBindingAdaptorType)obj).ILInstance.Type.BaseType.GetVirtualMethod(m); } } Free(objRef); esp = PushObject(objRef, mStack, m); } break; #endregion #region Compare case OpCodeEnum.Ceq: { StackObject* obj1 = esp - 1 - 1; StackObject* obj2 = esp - 1; bool res = false; if (obj1->ObjectType == obj2->ObjectType) { switch (obj1->ObjectType) { case ObjectTypes.Integer: case ObjectTypes.Float: res = obj1->Value == obj2->Value; break; case ObjectTypes.Object: res = mStack[obj1->Value] == mStack[obj2->Value]; break; case ObjectTypes.FieldReference: res = mStack[obj1->Value] == mStack[obj2->Value] && obj1->ValueLow == obj2->ValueLow; break; case ObjectTypes.Null: res = true; break; default: res = obj1->Value == obj2->Value && obj1->ValueLow == obj2->ValueLow; break; } } else { switch (obj1->ObjectType) { case ObjectTypes.Object: res = mStack[obj1->Value] == null && obj2->ObjectType == ObjectTypes.Null; break; case ObjectTypes.Null: res = obj2->ObjectType == ObjectTypes.Object && mStack[obj2->Value] == null; break; } } Free(esp - 1); Free(esp - 1 - 1); if (res) esp = PushOne(esp - 1 - 1); else esp = PushZero(esp - 1 - 1); } break; case OpCodeEnum.Clt: { StackObject* obj1 = esp - 1 - 1; StackObject* obj2 = esp - 1; bool res = false; switch (obj1->ObjectType) { case ObjectTypes.Integer: res = obj1->Value < obj2->Value; break; case ObjectTypes.Long: res = *(long*)&obj1->Value < *(long*)&obj2->Value; break; case ObjectTypes.Float: res = *(float*)&obj1->Value < *(float*)&obj2->Value; break; case ObjectTypes.Double: res = *(double*)&obj1->Value < *(double*)&obj2->Value; break; default: throw new NotImplementedException(); } if (res) esp = PushOne(esp - 1 - 1); else esp = PushZero(esp - 1 - 1); } break; case OpCodeEnum.Clt_Un: { StackObject* obj1 = esp - 1 - 1; StackObject* obj2 = esp - 1; bool res = false; switch (obj1->ObjectType) { case ObjectTypes.Integer: res = (uint)obj1->Value < (uint)obj2->Value && obj2->ObjectType != ObjectTypes.Null; break; case ObjectTypes.Long: res = (ulong)*(long*)&obj1->Value < (ulong)*(long*)&obj2->Value && obj2->ObjectType != ObjectTypes.Null; break; case ObjectTypes.Float: res = *(float*)&obj1->Value < *(float*)&obj2->Value && obj2->ObjectType != ObjectTypes.Null; break; case ObjectTypes.Double: res = *(double*)&obj1->Value < *(double*)&obj2->Value && obj2->ObjectType != ObjectTypes.Null; break; default: throw new NotImplementedException(); } if (res) esp = PushOne(esp - 1 - 1); else esp = PushZero(esp - 1 - 1); } break; case OpCodeEnum.Cgt: { StackObject* obj1 = esp - 1 - 1; StackObject* obj2 = esp - 1; bool res = false; switch (obj1->ObjectType) { case ObjectTypes.Integer: res = obj1->Value > obj2->Value || obj2->ObjectType == ObjectTypes.Null; break; case ObjectTypes.Long: res = *(long*)&obj1->Value > *(long*)&obj2->Value || obj2->ObjectType == ObjectTypes.Null; break; case ObjectTypes.Float: res = *(float*)&obj1->Value > *(float*)&obj2->Value || obj2->ObjectType == ObjectTypes.Null; break; case ObjectTypes.Double: res = *(double*)&obj1->Value > *(double*)&obj2->Value || obj2->ObjectType == ObjectTypes.Null; break; default: throw new NotImplementedException(); } if (res) esp = PushOne(esp - 1 - 1); else esp = PushZero(esp - 1 - 1); } break; case OpCodeEnum.Cgt_Un: { StackObject* obj1 = esp - 1 - 1; StackObject* obj2 = esp - 1; bool res = false; switch (obj1->ObjectType) { case ObjectTypes.Integer: res = ((uint)obj1->Value > (uint)obj2->Value) || obj2->ObjectType == ObjectTypes.Null; break; case ObjectTypes.Long: res = (ulong)*(long*)&obj1->Value > (ulong)*(long*)&obj2->Value || obj2->ObjectType == ObjectTypes.Null; break; case ObjectTypes.Float: res = *(float*)&obj1->Value > *(float*)&obj2->Value || obj2->ObjectType == ObjectTypes.Null; break; case ObjectTypes.Double: res = *(double*)&obj1->Value > *(double*)&obj2->Value || obj2->ObjectType == ObjectTypes.Null; break; case ObjectTypes.Object: res = mStack[obj1->Value] != null && obj2->ObjectType == ObjectTypes.Null; break; case ObjectTypes.Null: res = false; break; default: throw new NotImplementedException(); } if (res) esp = PushOne(esp - 1 - 1); else esp = PushZero(esp - 1 - 1); } break; #endregion #region Initialization & Instantiation case OpCodeEnum.Newobj: { IMethod m = domain.GetMethod(ip->TokenInteger); if (m is ILMethod) { ILType type = m.DeclearingType as ILType; if (type.IsDelegate) { var objRef = GetObjectAndResolveReference(esp - 1 - 1); var mi = (IMethod)mStack[(esp - 1)->Value]; object ins; if (objRef->ObjectType == ObjectTypes.Null) ins = null; else ins = mStack[objRef->Value]; Free(esp - 1); Free(esp - 1 - 1); esp = esp - 1 - 1; object dele; if (mi is ILMethod) { if (ins != null) { dele = ((ILTypeInstance)ins).GetDelegateAdapter((ILMethod)mi); if (dele == null) dele = domain.DelegateManager.FindDelegateAdapter((ILTypeInstance)ins, (ILMethod)mi); } else { if (((ILMethod)mi).DelegateAdapter == null) { ((ILMethod)mi).DelegateAdapter = domain.DelegateManager.FindDelegateAdapter(null, (ILMethod)mi); } dele = ((ILMethod)mi).DelegateAdapter; } } else { throw new NotImplementedException(); } esp = PushObject(esp, mStack, dele); } else { var a = esp - m.ParameterCount; StackObject* objRef; ILTypeInstance obj = null; bool isValueType = type.IsValueType; if (isValueType) { stack.AllocValueType(esp, type); objRef = esp + 1; objRef->ObjectType = ObjectTypes.StackObjectReference; *(StackObject**)&objRef->Value = esp; objRef++; } else { obj = type.Instantiate(false); objRef = PushObject(esp, mStack, obj);//this parameter for constructor } esp = objRef; for (int i = 0; i < m.ParameterCount; i++) { CopyToStack(esp, a + i, mStack); esp++; } esp = Execute((ILMethod)m, esp, out unhandledException); ValueTypeBasePointer = bp; if (isValueType) { var ins = objRef - 1 - 1; *a = *ins; esp = a + 1; } else esp = PushObject(a, mStack, obj);//new constructedObj } if (unhandledException) returned = true; } else { CLRMethod cm = (CLRMethod)m; //Means new object(); if (cm == null) { esp = PushObject(esp, mStack, new object()); } else { if (cm.DeclearingType.IsDelegate) { var objRef = GetObjectAndResolveReference(esp - 1 - 1); var mi = (IMethod)mStack[(esp - 1)->Value]; object ins; if (objRef->ObjectType == ObjectTypes.Null) ins = null; else ins = mStack[objRef->Value]; Free(esp - 1); Free(esp - 1 - 1); esp = esp - 1 - 1; object dele; if (mi is ILMethod) { if (ins != null) { dele = ((ILTypeInstance)ins).GetDelegateAdapter((ILMethod)mi); if (dele == null) dele = domain.DelegateManager.FindDelegateAdapter((ILTypeInstance)ins, (ILMethod)mi); } else { if (((ILMethod)mi).DelegateAdapter == null) { ((ILMethod)mi).DelegateAdapter = domain.DelegateManager.FindDelegateAdapter(null, (ILMethod)mi); } dele = ((ILMethod)mi).DelegateAdapter; } } else { if (ins is ILTypeInstance) ins = ((ILTypeInstance)ins).CLRInstance; dele = Delegate.CreateDelegate(cm.DeclearingType.TypeForCLR, ins, ((CLRMethod)mi).MethodInfo); } esp = PushObject(esp, mStack, dele); } else { var redirect = cm.Redirection; if (redirect != null) esp = redirect(this, esp, mStack, cm, true); else { object result = cm.Invoke(this, esp, mStack, true); int paramCount = cm.ParameterCount; for (int i = 1; i <= paramCount; i++) { Free(esp - i); } esp = Minus(esp, paramCount); esp = PushObject(esp, mStack, result);//new constructedObj } } } } } break; case OpCodeEnum.Constrained: { var objRef = esp - 1; var obj = GetObjectAndResolveReference(objRef); var type = domain.GetType(ip->TokenInteger); if (type != null) { if (type is ILType) { var t = (ILType)type; if (t.IsEnum) { ILEnumTypeInstance ins = new ILEnumTypeInstance(t); switch (obj->ObjectType) { case ObjectTypes.FieldReference: { var owner = mStack[obj->Value] as ILTypeInstance; int idx = obj->ValueLow; Free(objRef); owner.PushToStack(idx, objRef, AppDomain, mStack); ins.AssignFromStack(0, objRef, AppDomain, mStack); ins.Boxed = true; } break; case ObjectTypes.StaticFieldReference: { var st = AppDomain.GetType(obj->Value) as ILType; int idx = obj->ValueLow; Free(objRef); st.StaticInstance.PushToStack(idx, objRef, AppDomain, mStack); ins.AssignFromStack(0, objRef, AppDomain, mStack); ins.Boxed = true; } break; case ObjectTypes.ArrayReference: { var arr = mStack[obj->Value]; var idx = obj->ValueLow; Free(objRef); LoadFromArrayReference(arr, idx, objRef, t, mStack); ins.AssignFromStack(0, objRef, AppDomain, mStack); ins.Boxed = true; } break; default: ins.AssignFromStack(0, obj, AppDomain, mStack); ins.Boxed = true; break; } esp = PushObject(esp - 1, mStack, ins); } else { //Nothing to do for normal IL Types } } else { var tt = type.TypeForCLR; if (tt.IsEnum) { esp = PushObject(esp - 1, mStack, Enum.ToObject(tt, StackObject.ToObject(obj, AppDomain, mStack))); } else if (tt.IsPrimitive) { esp = PushObject(esp - 1, mStack, tt.CheckCLRTypes(StackObject.ToObject(obj, AppDomain, mStack))); } else { //Nothing to do for other CLR types } } } else throw new NullReferenceException(); } break; case OpCodeEnum.Box: { var obj = esp - 1; var type = domain.GetType(ip->TokenInteger); if (type != null) { if (type is ILType) { if (((ILType)type).IsEnum) { ILEnumTypeInstance ins = new Intepreter.ILEnumTypeInstance((ILType)type); ins.AssignFromStack(0, obj, AppDomain, mStack); ins.Boxed = true; esp = PushObject(obj, mStack, ins, true); } else { switch (obj->ObjectType) { case ObjectTypes.Null: break; case ObjectTypes.ValueTypeObjectReference: { ILTypeInstance ins = ((ILType)type).Instantiate(false); ins.AssignFromStack(obj, domain, mStack); FreeStackValueType(obj); esp = PushObject(obj, mStack, ins, true); } break; default: { var val = mStack[obj->Value]; Free(obj); ILTypeInstance ins = (ILTypeInstance)val; if (ins != null) { if (ins.IsValueType) { ins.Boxed = true; } esp = PushObject(obj, mStack, ins, true); } else { esp = PushNull(obj); } } break; } } } else { if (type.TypeForCLR.IsPrimitive) { var t = type.TypeForCLR; if (t == typeof(int)) { switch (obj->ObjectType) { case ObjectTypes.Integer: esp = PushObject(obj, mStack, obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, 0, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(bool)) { switch (obj->ObjectType) { case ObjectTypes.Integer: esp = PushObject(obj, mStack, (obj->Value == 1), true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, false, true); break; case ObjectTypes.Object: break; default: throw new NotImplementedException(); } } else if (t == typeof(byte)) { switch (obj->ObjectType) { case ObjectTypes.Integer: esp = PushObject(obj, mStack, (byte)obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, 0L, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(short)) { switch (obj->ObjectType) { case ObjectTypes.Integer: esp = PushObject(obj, mStack, (short)obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, (short)0, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(long)) { switch (obj->ObjectType) { case ObjectTypes.Long: esp = PushObject(obj, mStack, *(long*)&obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, 0L, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(float)) { switch (obj->ObjectType) { case ObjectTypes.Float: esp = PushObject(obj, mStack, *(float*)&obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, 0f, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(double)) { switch (obj->ObjectType) { case ObjectTypes.Double: esp = PushObject(obj, mStack, *(double*)&obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, 0.0, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(char)) { switch (obj->ObjectType) { case ObjectTypes.Integer: esp = PushObject(obj, mStack, (char)obj->Value, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(uint)) { switch (obj->ObjectType) { case ObjectTypes.Integer: esp = PushObject(obj, mStack, (uint)obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, (uint)0, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(ushort)) { switch (obj->ObjectType) { case ObjectTypes.Integer: esp = PushObject(obj, mStack, (ushort)obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, (ushort)0, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(ulong)) { switch (obj->ObjectType) { case ObjectTypes.Long: esp = PushObject(obj, mStack, *(ulong*)&obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, (ulong)0, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(sbyte)) { switch (obj->ObjectType) { case ObjectTypes.Integer: esp = PushObject(obj, mStack, (sbyte)obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, (sbyte)0, true); break; default: throw new NotImplementedException(); } } else throw new NotImplementedException(); } else if (type.TypeForCLR.IsEnum) { esp = PushObject(obj, mStack, Enum.ToObject(type.TypeForCLR, StackObject.ToObject(obj, AppDomain, mStack)), true); } else { if(obj->ObjectType== ObjectTypes.ValueTypeObjectReference) { var dst = *(StackObject**)&obj->Value; var vt = domain.GetType(dst->Value); if (vt != type) throw new InvalidCastException(); object ins = ((CLRType)vt).ValueTypeBinder.ToObject(dst, mStack); FreeStackValueType(obj); esp = PushObject(obj, mStack, ins, true); } //nothing to do for CLR type boxing } } } else throw new NullReferenceException(); } break; case OpCodeEnum.Unbox: case OpCodeEnum.Unbox_Any: { var objRef = esp - 1; if (objRef->ObjectType == ObjectTypes.Object) { object obj = mStack[objRef->Value]; Free(objRef); if (obj != null) { var t = domain.GetType(ip->TokenInteger); if (t != null) { var type = t.TypeForCLR; if ((t is CLRType) && type.IsPrimitive) { if (type == typeof(int)) { int val = obj.ToInt32(); objRef->ObjectType = ObjectTypes.Integer; objRef->Value = val; } else if (type == typeof(bool)) { bool val = (bool)obj; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = val ? 1 : 0; } else if (type == typeof(short)) { short val = obj.ToInt16(); objRef->ObjectType = ObjectTypes.Integer; objRef->Value = val; } else if (type == typeof(long)) { long val = obj.ToInt64(); objRef->ObjectType = ObjectTypes.Long; *(long*)&objRef->Value = val; } else if (type == typeof(float)) { float val = obj.ToFloat(); objRef->ObjectType = ObjectTypes.Float; *(float*)&objRef->Value = val; } else if (type == typeof(byte)) { byte val = (byte)obj; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = val; } else if (type == typeof(double)) { double val = obj.ToDouble(); objRef->ObjectType = ObjectTypes.Double; *(double*)&objRef->Value = val; } else if (type == typeof(char)) { char val = (char)obj; objRef->ObjectType = ObjectTypes.Integer; *(char*)&objRef->Value = val; } else if (type == typeof(uint)) { uint val = (uint)obj; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = (int)val; } else if (type == typeof(ushort)) { ushort val = (ushort)obj; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = val; } else if (type == typeof(ulong)) { ulong val = (ulong)obj; objRef->ObjectType = ObjectTypes.Long; *(ulong*)&objRef->Value = val; } else if (type == typeof(sbyte)) { sbyte val = (sbyte)obj; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = val; } else throw new NotImplementedException(); } else if (t.IsValueType) { if (obj is ILTypeInstance) { var res = ((ILTypeInstance)obj); if (res is ILEnumTypeInstance) { res.PushToStack(0, objRef, AppDomain, mStack); } else { if (res.Boxed) { res = res.Clone(); res.Boxed = false; } PushObject(objRef, mStack, res); } } else PushObject(objRef, mStack, obj); } else { PushObject(objRef, mStack, obj); } } else throw new TypeLoadException(); } else throw new NullReferenceException(); } else if (objRef->ObjectType < ObjectTypes.StackObjectReference) { //Nothing to do with primitive types } else throw new InvalidCastException(); } break; case OpCodeEnum.Initobj: { var objRef = GetObjectAndResolveReference(esp - 1); var type = domain.GetType(ip->TokenInteger); if (type is ILType) { ILType it = (ILType)type; if (it.IsValueType) { switch (objRef->ObjectType) { case ObjectTypes.Null: throw new NullReferenceException(); case ObjectTypes.ValueTypeObjectReference: stack.ClearValueTypeObject(type, *(StackObject**)&objRef->Value); break; case ObjectTypes.Object: { var obj = mStack[objRef->Value]; if (obj != null) { if (obj is ILTypeInstance) { ILTypeInstance instance = obj as ILTypeInstance; instance.Clear(); } else throw new NotSupportedException(); } else throw new NullReferenceException(); } break; default: throw new NotImplementedException(); } Free(esp - 1); esp--; } else { PushNull(esp); switch (objRef->ObjectType) { case ObjectTypes.StaticFieldReference: { var t = AppDomain.GetType(objRef->Value) as ILType; t.StaticInstance.AssignFromStack(objRef->ValueLow, esp, AppDomain, mStack); } break; case ObjectTypes.FieldReference: { var instance = mStack[objRef->Value] as ILTypeInstance; instance.AssignFromStack(objRef->ValueLow, esp, AppDomain, mStack); Free(esp - 1); esp--; } break; default: { if (objRef->ObjectType >= ObjectTypes.Object) mStack[objRef->Value] = null; else PushNull(objRef); } break; } } } else { if (objRef->ObjectType == ObjectTypes.ValueTypeObjectReference) { stack.ClearValueTypeObject(type, *(StackObject**)&objRef->Value); } Free(esp - 1); esp--; } } break; case OpCodeEnum.Isinst: { var objRef = esp - 1; var type = domain.GetType(ip->TokenInteger); if (type != null) { objRef = GetObjectAndResolveReference(objRef); if (objRef->ObjectType <= ObjectTypes.Double) { var tclr = type.TypeForCLR; switch (objRef->ObjectType) { case ObjectTypes.Integer: { if (tclr != typeof(int) && tclr != typeof(bool) && tclr != typeof(short) && tclr != typeof(byte) && tclr != typeof(ushort) && tclr !=typeof(uint)) { objRef->ObjectType = ObjectTypes.Null; objRef->Value = -1; objRef->ValueLow = 0; } } break; case ObjectTypes.Long: { if (tclr != typeof(long) && tclr != typeof(ulong)) { objRef->ObjectType = ObjectTypes.Null; objRef->Value = -1; objRef->ValueLow = 0; } } break; case ObjectTypes.Float: { if (tclr != typeof(float)) { objRef->ObjectType = ObjectTypes.Null; objRef->Value = -1; objRef->ValueLow = 0; } } break; case ObjectTypes.Double: { if (tclr != typeof(double)) { objRef->ObjectType = ObjectTypes.Null; objRef->Value = -1; objRef->ValueLow = 0; } } break; case ObjectTypes.Null: objRef->ObjectType = ObjectTypes.Null; objRef->Value = -1; objRef->ValueLow = 0; break; } } else { var obj = RetriveObject(objRef, mStack); Free(objRef); if (obj != null) { if (obj is ILTypeInstance) { if (((ILTypeInstance)obj).CanAssignTo(type)) { esp = PushObject(objRef, mStack, obj); } else { #if !DEBUG objRef->ObjectType = ObjectTypes.Null; objRef->Value = -1; objRef->ValueLow = 0; #endif } } else { if (type.TypeForCLR.IsAssignableFrom(obj.GetType())) { esp = PushObject(objRef, mStack, obj, true); } else { #if !DEBUG objRef->ObjectType = ObjectTypes.Null; objRef->Value = -1; objRef->ValueLow = 0; #endif } } } else { #if !DEBUG objRef->ObjectType = ObjectTypes.Null; objRef->Value = -1; objRef->ValueLow = 0; #endif } } } else throw new NullReferenceException(); } break; #endregion #region Array case OpCodeEnum.Newarr: { var cnt = (esp - 1); var type = domain.GetType(ip->TokenInteger); object arr = null; if (type != null) { if (type.TypeForCLR != typeof(ILTypeInstance)) { if (type is CLRType) { arr = ((CLRType)type).CreateArrayInstance(cnt->Value); } else { arr = Array.CreateInstance(type.TypeForCLR, cnt->Value); } //Register Type AppDomain.GetType(arr.GetType()); } else { arr = new ILTypeInstance[cnt->Value]; } } cnt->ObjectType = ObjectTypes.Object; cnt->Value = mStack.Count; mStack.Add(arr); } break; case OpCodeEnum.Stelem_Ref: case OpCodeEnum.Stelem_Any: { var val = GetObjectAndResolveReference(esp - 1); var idx = esp - 1 - 1; var arrRef = esp - 1 - 1 - 1; Array arr = mStack[arrRef->Value] as Array; if (arr is object[]) { switch (val->ObjectType) { case ObjectTypes.Null: arr.SetValue(null, idx->Value); break; case ObjectTypes.Object: ArraySetValue(arr, mStack[val->Value], idx->Value); break; case ObjectTypes.Integer: arr.SetValue(val->Value, idx->Value); break; case ObjectTypes.Long: arr.SetValue(*(long*)&val->Value, idx->Value); break; case ObjectTypes.Float: arr.SetValue(*(float*)&val->Value, idx->Value); break; case ObjectTypes.Double: arr.SetValue(*(double*)&val->Value, idx->Value); break; default: throw new NotImplementedException(); } } else { switch (val->ObjectType) { case ObjectTypes.Object: ArraySetValue(arr, mStack[val->Value], idx->Value); break; case ObjectTypes.Integer: { StoreIntValueToArray(arr, val, idx); } break; case ObjectTypes.Long: { if (arr is long[]) { ((long[])arr)[idx->Value] = *(long*)&val->Value; } else { ((ulong[])arr)[idx->Value] = *(ulong*)&val->Value; } } break; case ObjectTypes.Float: { ((float[])arr)[idx->Value] = *(float*)&val->Value; } break; case ObjectTypes.Double: { ((double[])arr)[idx->Value] = *(double*)&val->Value; } break; default: throw new NotImplementedException(); } } Free(esp - 1); Free(esp - 1 - 1); Free(esp - 1 - 1 - 1); esp = esp - 1 - 1 - 1; } break; case OpCodeEnum.Ldelem_Ref: case OpCodeEnum.Ldelem_Any: { var idx = esp - 1; var arrRef = esp - 1 - 1; Array arr = mStack[arrRef->Value] as Array; object val = arr.GetValue(idx->Value); if (val is CrossBindingAdaptorType) val = ((CrossBindingAdaptorType)val).ILInstance; Free(esp - 1); Free(esp - 1 - 1); esp = PushObject(esp - 1 - 1, mStack, val); } break; case OpCodeEnum.Stelem_I1: { var val = esp - 1; var idx = esp - 1 - 1; var arrRef = esp - 1 - 1 - 1; byte[] arr = mStack[arrRef->Value] as byte[]; if (arr != null) { arr[idx->Value] = (byte)val->Value; } else { bool[] arr2 = mStack[arrRef->Value] as bool[]; if (arr2 != null) { arr2[idx->Value] = val->Value == 1; } else { sbyte[] arr3 = mStack[arrRef->Value] as sbyte[]; arr3[idx->Value] = (sbyte)val->Value; } } Free(esp - 1); Free(esp - 1 - 1); Free(esp - 1 - 1 - 1); esp = esp - 1 - 1 - 1; } break; case OpCodeEnum.Ldelem_I1: { var idx = esp - 1; var arrRef = esp - 1 - 1; bool[] arr = mStack[arrRef->Value] as bool[]; int val; if (arr != null) val = arr[idx->Value] ? 1 : 0; else { sbyte[] arr2 = mStack[arrRef->Value] as sbyte[]; val = arr2[idx->Value]; } Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.Integer; arrRef->Value = val; esp -= 1; } break; case OpCodeEnum.Ldelem_U1: { var idx = (esp - 1); var arrRef = esp - 1 - 1; byte[] arr = mStack[arrRef->Value] as byte[]; int val; if (arr != null) val = arr[idx->Value]; else { bool[] arr2 = mStack[arrRef->Value] as bool[]; val = arr2[idx->Value] ? 1 : 0; } Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.Integer; arrRef->Value = val; esp -= 1; } break; case OpCodeEnum.Stelem_I2: { var val = esp - 1; var idx = esp - 1 - 1; var arrRef = esp - 1 - 1 - 1; short[] arr = mStack[arrRef->Value] as short[]; if (arr != null) { arr[idx->Value] = (short)val->Value; } else { ushort[] arr2 = mStack[arrRef->Value] as ushort[]; if (arr2 != null) { arr2[idx->Value] = (ushort)val->Value; } else { char[] arr3 = mStack[arrRef->Value] as char[]; arr3[idx->Value] = (char)val->Value; } } Free(esp - 1); Free(esp - 1 - 1); Free(esp - 1 - 1 - 1); esp = esp - 1 - 1 - 1; } break; case OpCodeEnum.Ldelem_I2: { var idx = (esp - 1)->Value; var arrRef = esp - 1 - 1; short[] arr = mStack[arrRef->Value] as short[]; int val = 0; if (arr != null) { val = arr[idx]; } else { char[] arr2 = mStack[arrRef->Value] as char[]; val = arr2[idx]; } Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.Integer; arrRef->Value = val; esp -= 1; } break; case OpCodeEnum.Ldelem_U2: { var idx = (esp - 1)->Value; var arrRef = esp - 1 - 1; ushort[] arr = mStack[arrRef->Value] as ushort[]; int val = 0; if (arr != null) { val = arr[idx]; } else { char[] arr2 = mStack[arrRef->Value] as char[]; val = arr2[idx]; } Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.Integer; arrRef->Value = val; esp -= 1; } break; case OpCodeEnum.Stelem_I4: { var val = esp - 1; var idx = esp - 1 - 1; var arrRef = esp - 1 - 1 - 1; int[] arr = mStack[arrRef->Value] as int[]; if (arr != null) { arr[idx->Value] = val->Value; } else { uint[] arr2 = mStack[arrRef->Value] as uint[]; arr2[idx->Value] = (uint)val->Value; } Free(esp - 1); Free(esp - 1 - 1); Free(esp - 1 - 1 - 1); esp = esp - 1 - 1 - 1; } break; case OpCodeEnum.Ldelem_I4: { var idx = (esp - 1)->Value; var arrRef = esp - 1 - 1; int[] arr = mStack[arrRef->Value] as int[]; Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.Integer; arrRef->Value = arr[idx]; esp -= 1; } break; case OpCodeEnum.Ldelem_U4: { var idx = (esp - 1)->Value; var arrRef = esp - 1 - 1; uint[] arr = mStack[arrRef->Value] as uint[]; Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.Integer; arrRef->Value = (int)arr[idx]; esp -= 1; } break; case OpCodeEnum.Stelem_I8: { var val = esp - 1; var idx = esp - 1 - 1; var arrRef = esp - 1 - 1 - 1; long[] arr = mStack[arrRef->Value] as long[]; if (arr != null) { arr[idx->Value] = *(long*)&val->Value; } else { ulong[] arr2 = mStack[arrRef->Value] as ulong[]; arr2[idx->Value] = *(ulong*)&val->Value; } Free(esp - 1); Free(esp - 1 - 1); Free(esp - 1 - 1 - 1); esp = esp - 1 - 1 - 1; } break; case OpCodeEnum.Ldelem_I8: { var idx = esp - 1; var arrRef = esp - 1 - 1; long[] arr = mStack[arrRef->Value] as long[]; long val; if (arr != null) val = arr[idx->Value]; else { ulong[] arr2 = mStack[arrRef->Value] as ulong[]; val = (long)arr2[idx->Value]; } Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.Long; *(long*)&arrRef->Value = val; esp -= 1; } break; case OpCodeEnum.Stelem_R4: { var val = esp - 1; var idx = esp - 1 - 1; var arrRef = esp - 1 - 1 - 1; float[] arr = mStack[arrRef->Value] as float[]; arr[idx->Value] = *(float*)&val->Value; Free(esp - 1); Free(esp - 1 - 1); Free(esp - 1 - 1 - 1); esp = esp - 1 - 1 - 1; } break; case OpCodeEnum.Ldelem_R4: { var idx = (esp - 1)->Value; var arrRef = esp - 1 - 1; float[] arr = mStack[arrRef->Value] as float[]; Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.Float; *(float*)&arrRef->Value = arr[idx]; esp -= 1; } break; case OpCodeEnum.Stelem_R8: { var val = esp - 1; var idx = esp - 1 - 1; var arrRef = esp - 1 - 1 - 1; double[] arr = mStack[arrRef->Value] as double[]; arr[idx->Value] = *(double*)&val->Value; Free(esp - 1); Free(esp - 1 - 1); Free(esp - 1 - 1 - 1); esp = esp - 1 - 1 - 1; } break; case OpCodeEnum.Ldelem_R8: { var idx = (esp - 1)->Value; var arrRef = esp - 1 - 1; double[] arr = mStack[arrRef->Value] as double[]; Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.Double; *(double*)&arrRef->Value = arr[idx]; esp -= 1; } break; case OpCodeEnum.Ldlen: { var arrRef = esp - 1; Array arr = mStack[arrRef->Value] as Array; Free(esp - 1); arrRef->ObjectType = ObjectTypes.Integer; arrRef->Value = arr.Length; } break; case OpCodeEnum.Ldelema: { var arrRef = esp - 1 - 1; var idx = (esp - 1)->Value; Array arr = mStack[arrRef->Value] as Array; Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.ArrayReference; arrRef->Value = mStack.Count; mStack.Add(arr); arrRef->ValueLow = idx; esp--; } break; #endregion #region Conversion case OpCodeEnum.Conv_U1: case OpCodeEnum.Conv_Ovf_U1: case OpCodeEnum.Conv_Ovf_U1_Un: { var obj = esp - 1; int val; switch (obj->ObjectType) { case ObjectTypes.Long: case ObjectTypes.Integer: val = (byte)obj->Value; break; case ObjectTypes.Float: val = (byte)*(float*)&obj->Value; break; case ObjectTypes.Double: val = (byte)*(double*)&obj->Value; break; default: throw new NotImplementedException(); } obj->ObjectType = ObjectTypes.Integer; obj->Value = val; obj->ValueLow = 0; } break; case OpCodeEnum.Conv_I1: case OpCodeEnum.Conv_Ovf_I1: case OpCodeEnum.Conv_Ovf_I1_Un: { var obj = esp - 1; int val; switch (obj->ObjectType) { case ObjectTypes.Long: case ObjectTypes.Integer: val = (sbyte)obj->Value; break; case ObjectTypes.Float: val = (sbyte)*(float*)&obj->Value; break; case ObjectTypes.Double: val = (sbyte)*(double*)&obj->Value; break; default: throw new NotImplementedException(); } obj->ObjectType = ObjectTypes.Integer; obj->Value = val; obj->ValueLow = 0; } break; case OpCodeEnum.Conv_U2: case OpCodeEnum.Conv_Ovf_U2: case OpCodeEnum.Conv_Ovf_U2_Un: { var obj = esp - 1; int val; switch (obj->ObjectType) { case ObjectTypes.Long: case ObjectTypes.Integer: val = (ushort)obj->Value; break; case ObjectTypes.Float: val = (ushort)*(float*)&obj->Value; break; case ObjectTypes.Double: val = (ushort)*(double*)&obj->Value; break; default: throw new NotImplementedException(); } obj->ObjectType = ObjectTypes.Integer; obj->Value = val; obj->ValueLow = 0; } break; case OpCodeEnum.Conv_I2: case OpCodeEnum.Conv_Ovf_I2: case OpCodeEnum.Conv_Ovf_I2_Un: { var obj = esp - 1; int val; switch (obj->ObjectType) { case ObjectTypes.Long: case ObjectTypes.Integer: val = (short)(obj->Value); break; case ObjectTypes.Float: val = (short)*(float*)&obj->Value; break; case ObjectTypes.Double: val = (short)*(double*)&obj->Value; break; default: throw new NotImplementedException(); } obj->ObjectType = ObjectTypes.Integer; obj->Value = val; obj->ValueLow = 0; } break; case OpCodeEnum.Conv_U4: case OpCodeEnum.Conv_Ovf_U4: case OpCodeEnum.Conv_Ovf_U4_Un: { var obj = esp - 1; uint val; switch (obj->ObjectType) { case ObjectTypes.Long: val = (uint)*(long*)&obj->Value; break; case ObjectTypes.Integer: val = (uint)obj->Value; break; case ObjectTypes.Float: val = (uint)*(float*)&obj->Value; break; case ObjectTypes.Double: val = (uint)*(double*)&obj->Value; break; default: throw new NotImplementedException(); } obj->ObjectType = ObjectTypes.Integer; obj->Value = (int)val; obj->ValueLow = 0; } break; case OpCodeEnum.Conv_I4: case OpCodeEnum.Conv_Ovf_I: case OpCodeEnum.Conv_Ovf_I_Un: case OpCodeEnum.Conv_Ovf_I4: case OpCodeEnum.Conv_Ovf_I4_Un: { var obj = esp - 1; int val; switch (obj->ObjectType) { case ObjectTypes.Long: val = (int)*(long*)&obj->Value; break; case ObjectTypes.Float: val = (int)*(float*)&obj->Value; break; case ObjectTypes.Double: val = (int)*(double*)&obj->Value; break; case ObjectTypes.Integer: val = obj->Value; break; default: throw new NotImplementedException(); } obj->ObjectType = ObjectTypes.Integer; obj->Value = val; } break; case OpCodeEnum.Conv_U8: case OpCodeEnum.Conv_I8: case OpCodeEnum.Conv_Ovf_I8: case OpCodeEnum.Conv_Ovf_I8_Un: case OpCodeEnum.Conv_Ovf_U8: case OpCodeEnum.Conv_Ovf_U8_Un: { var obj = esp - 1; long val; switch (obj->ObjectType) { case ObjectTypes.Integer: val = obj->Value; break; case ObjectTypes.Long: ip++; continue; case ObjectTypes.Float: val = (long)*(float*)&obj->Value; break; case ObjectTypes.Double: val = (long)*(double*)&obj->Value; break; default: throw new NotImplementedException(); } obj->ObjectType = ObjectTypes.Long; *(long*)(&obj->Value) = val; } break; case OpCodeEnum.Conv_R4: { var obj = esp - 1; float val; switch (obj->ObjectType) { case ObjectTypes.Long: val = (float)*(long*)&obj->Value; break; case ObjectTypes.Float: ip++; continue; case ObjectTypes.Double: val = (float)*(double*)&obj->Value; break; case ObjectTypes.Integer: val = obj->Value; break; default: throw new NotImplementedException(); } obj->ObjectType = ObjectTypes.Float; *(float*)&obj->Value = val; } break; case OpCodeEnum.Conv_R8: { var obj = esp - 1; double val; switch (obj->ObjectType) { case ObjectTypes.Long: val = (double)*(long*)&obj->Value; break; case ObjectTypes.Float: val = *(float*)&obj->Value; break; case ObjectTypes.Integer: val = obj->Value; break; case ObjectTypes.Double: ip++; continue; default: throw new NotImplementedException(); } obj->ObjectType = ObjectTypes.Double; *(double*)&obj->Value = val; } break; case OpCodeEnum.Conv_R_Un: { var obj = esp - 1; bool isDouble = false; float val = 0; double val2 = 0; switch (obj->ObjectType) { case ObjectTypes.Long: val2 = (double)*(ulong*)&obj->Value; isDouble = true; break; case ObjectTypes.Float: ip++; continue; case ObjectTypes.Integer: val = (uint)obj->Value; break; case ObjectTypes.Double: ip++; continue; default: throw new NotImplementedException(); } if (isDouble) { obj->ObjectType = ObjectTypes.Double; *(double*)&obj->Value = val2; } else { obj->ObjectType = ObjectTypes.Float; *(float*)&obj->Value = val; } } break; #endregion #region Stack operation case OpCodeEnum.Pop: { Free(esp - 1); esp--; } break; case OpCodeEnum.Dup: { var obj = esp - 1; *esp = *obj; if (esp->ObjectType >= ObjectTypes.Object) { esp->Value = mStack.Count; mStack.Add(mStack[obj->Value]); } esp++; } break; #endregion case OpCodeEnum.Throw: { var obj = GetObjectAndResolveReference(esp - 1); var ex = mStack[obj->Value] as Exception; Free(obj); esp--; throw ex; } case OpCodeEnum.Nop: case OpCodeEnum.Volatile: case OpCodeEnum.Castclass: break; default: throw new NotSupportedException("Not supported opcode " + code); } ip++; } catch (Exception ex) { if (method.ExceptionHandler != null) { int addr = (int)(ip - ptr); var eh = GetCorrespondingExceptionHandler(method, ex, addr, ExceptionHandlerType.Catch, true); if (eh == null) { eh = GetCorrespondingExceptionHandler(method, ex, addr, ExceptionHandlerType.Catch, false); } if (eh != null) { if (ex is ILRuntimeException) { ILRuntimeException ire = (ILRuntimeException)ex; var inner = ire.InnerException; inner.Data["ThisInfo"] = ire.ThisInfo; inner.Data["StackTrace"] = ire.StackTrace; inner.Data["LocalInfo"] = ire.LocalInfo; ex = inner; } else { var debugger = AppDomain.DebugService; if (method.HasThis) ex.Data["ThisInfo"] = debugger.GetThisInfo(this); else ex.Data["ThisInfo"] = ""; ex.Data["StackTrace"] = debugger.GetStackTrance(this); ex.Data["LocalInfo"] = debugger.GetLocalVariableInfo(this); } //Clear call stack while (stack.Frames.Peek().BasePointer != frame.BasePointer) { var f = stack.Frames.Peek(); esp = stack.PopFrame(ref f, esp); if (f.Method.ReturnType != AppDomain.VoidType) { Free(esp - 1); esp--; } } esp = PushObject(esp, mStack, ex); unhandledException = false; ip = ptr + eh.HandlerStart; continue; } } if (unhandledException) { throw ex; } unhandledException = true; returned = true; #if DEBUG if (!AppDomain.DebugService.Break(this, ex)) #endif { var newEx = new ILRuntimeException(ex.Message, this, method, ex); throw newEx; } } } } #if UNITY_EDITOR if (System.Threading.Thread.CurrentThread.ManagedThreadId == AppDomain.UnityMainThreadID) #if UNITY_5_5_OR_NEWER UnityEngine.Profiling.Profiler.EndSample(); #else UnityEngine.Profiler.EndSample(); #endif #endif //ClearStack return stack.PopFrame(ref frame, esp); } void DumpStack(StackObject* esp) { AppDomain.DebugService.DumpStack(esp, stack); } void CloneStackValueType(StackObject* src, StackObject* dst, IList mStack) { StackObject* descriptor = *(StackObject**)&src->Value; stack.AllocValueType(dst, AppDomain.GetType(descriptor->Value)); StackObject* dstDescriptor = *(StackObject**)&dst->Value; int cnt = descriptor->ValueLow; for(int i = 0; i < cnt; i++) { StackObject* val = Minus(descriptor, i + 1); CopyToValueTypeField(dstDescriptor, i, val, mStack); } } void CopyStackValueType(StackObject* src, StackObject* dst, IList mStack) { StackObject* descriptor = *(StackObject**)&src->Value; StackObject* dstDescriptor = *(StackObject**)&dst->Value; if (descriptor->Value != dstDescriptor->Value) throw new InvalidCastException(); int cnt = descriptor->ValueLow; for(int i = 0; i < cnt; i++) { StackObject* srcVal = Minus(descriptor, i + 1); StackObject* dstVal = Minus(dstDescriptor, i + 1); if (srcVal->ObjectType != dstVal->ObjectType) throw new NotSupportedException(); switch (dstVal->ObjectType) { case ObjectTypes.Object: case ObjectTypes.ArrayReference: case ObjectTypes.FieldReference: mStack[dstVal->Value] = mStack[srcVal->Value]; break; case ObjectTypes.ValueTypeObjectReference: CopyStackValueType(srcVal, dstVal, mStack); break; default: *dstVal = *srcVal; break; } } } void CopyToValueTypeField(StackObject* obj, int idx, StackObject* val, IList mStack) { StackObject* dst = Minus(obj, idx + 1); switch (val->ObjectType) { case ObjectTypes.Null: { mStack[dst->Value] = null; } break; case ObjectTypes.Object: case ObjectTypes.FieldReference: case ObjectTypes.ArrayReference: { if (dst->ObjectType == ObjectTypes.ValueTypeObjectReference) { var ins = mStack[val->Value]; dst = *(StackObject**)&dst->Value; if (ins is ILTypeInstance) { ((ILTypeInstance)ins).CopyValueTypeToStack(dst, mStack); } else { var vb = ((CLRType)domain.GetType(dst->Value)).ValueTypeBinder; vb.CopyValueTypeToStack(ins, dst, mStack); } } else { mStack[dst->Value] = CheckAndCloneValueType(mStack[val->Value], domain); } } break; case ObjectTypes.ValueTypeObjectReference: { if (dst->ObjectType == ObjectTypes.ValueTypeObjectReference) { CopyStackValueType(val, dst, mStack); } else throw new NotImplementedException(); } break; default: *dst = *val; break; } } void StLocSub(StackObject* esp, StackObject* v, StackObject* bp, int idx, IList mStack) { switch (esp->ObjectType) { case ObjectTypes.Null: v->ObjectType = ObjectTypes.Object; v->Value = idx; mStack[idx] = null; break; case ObjectTypes.Object: case ObjectTypes.FieldReference: case ObjectTypes.ArrayReference: if (v->ObjectType == ObjectTypes.ValueTypeObjectReference) { var obj = mStack[esp->Value]; if (obj is ILTypeInstance) { var dst = *(StackObject**)&v->Value; ((ILTypeInstance)obj).CopyValueTypeToStack(dst, mStack); } else { var dst = *(StackObject**)&v->Value; var ct = domain.GetType(dst->Value) as CLRType; var binder = ct.ValueTypeBinder; binder.CopyValueTypeToStack(obj, dst, mStack); } } else { *v = *esp; mStack[idx] = CheckAndCloneValueType(mStack[v->Value], domain); v->Value = idx; } Free(esp); break; case ObjectTypes.ValueTypeObjectReference: if (v->ObjectType == ObjectTypes.ValueTypeObjectReference) { CopyStackValueType(esp, v, mStack); } else throw new NotImplementedException(); FreeStackValueType(esp); break; default: *v = *esp; mStack[idx] = null; break; } } object RetriveObject(StackObject* esp, IList mStack) { StackObject* objRef = GetObjectAndResolveReference(esp); if (objRef->ObjectType == ObjectTypes.Null) return null; object obj = null; switch (objRef->ObjectType) { case ObjectTypes.Object: obj = mStack[objRef->Value]; break; case ObjectTypes.FieldReference: { obj = mStack[objRef->Value]; int idx = objRef->ValueLow; if (obj is ILTypeInstance) { obj = ((ILTypeInstance)obj)[idx]; } else { var t = AppDomain.GetType(obj.GetType()); obj = ((CLRType) t).GetFieldValue(idx, obj); } } break; case ObjectTypes.ArrayReference: { Array arr = mStack[objRef->Value] as Array; int idx = objRef->ValueLow; obj = arr.GetValue(idx); obj = obj.GetType().CheckCLRTypes(obj); } break; case ObjectTypes.StaticFieldReference: { var t = AppDomain.GetType(objRef->Value); int idx = objRef->ValueLow; if (t is ILType) { obj = ((ILType)t).StaticInstance[idx]; } else { obj = ((CLRType)t).GetFieldValue(idx, null); } } break; default: throw new NotImplementedException(); } return obj; } void ArraySetValue(Array arr, object obj, int idx) { if (obj == null) arr.SetValue(null, idx); else arr.SetValue(arr.GetType().GetElementType().CheckCLRTypes(obj), idx); } void StoreIntValueToArray(Array arr, StackObject* val, StackObject* idx) { { int[] tmp = arr as int[]; if (tmp != null) { tmp[idx->Value] = val->Value; return; } } { short[] tmp = arr as short[]; if (tmp != null) { tmp[idx->Value] = (short)val->Value; return; } } { byte[] tmp = arr as byte[]; if (tmp != null) { tmp[idx->Value] = (byte)val->Value; return; } } { bool[] tmp = arr as bool[]; if (tmp != null) { tmp[idx->Value] = val->Value == 1; return; } } { uint[] tmp = arr as uint[]; if (tmp != null) { tmp[idx->Value] = (uint)val->Value; return; } } { ushort[] tmp = arr as ushort[]; if (tmp != null) { tmp[idx->Value] = (ushort)val->Value; return; } } { char[] tmp = arr as char[]; if (tmp != null) { tmp[idx->Value] = (char)val->Value; return; } } { sbyte[] tmp = arr as sbyte[]; if (tmp != null) { tmp[idx->Value] = (sbyte)val->Value; return; } } throw new NotImplementedException(); } ExceptionHandler GetCorrespondingExceptionHandler(ILMethod method, object obj, int addr, ExceptionHandlerType type, bool explicitMatch) { ExceptionHandler res = null; int distance = int.MaxValue; Exception ex = obj is ILRuntimeException ? ((ILRuntimeException)obj).InnerException : obj as Exception; foreach (var i in method.ExceptionHandler) { if (i.HandlerType == type) { if (addr >= i.TryStart && addr <= i.TryEnd) { if (CheckExceptionType(i.CatchType, ex, explicitMatch)) { int d = addr - i.TryStart; if (d < distance) { distance = d; res = i; } } } } } return res; } void LoadFromFieldReference(object obj, int idx, StackObject* dst, IList mStack) { if (obj is ILTypeInstance) { ((ILTypeInstance)obj).PushToStack(idx, dst, AppDomain, mStack); } else { CLRType t = AppDomain.GetType(obj.GetType()) as CLRType; ILIntepreter.PushObject(dst, mStack, t.GetFieldValue(idx, obj)); } } void StoreValueToFieldReference(object obj, int idx, StackObject* val, IList mStack) { if (obj is ILTypeInstance) { ((ILTypeInstance)obj).AssignFromStack(idx, val, AppDomain, mStack); } else { CLRType t = AppDomain.GetType(obj.GetType()) as CLRType; var v = obj.GetType().CheckCLRTypes(CheckAndCloneValueType(StackObject.ToObject(val, AppDomain, mStack), AppDomain)); t.SetFieldValue(idx, ref obj, v); } } void LoadFromArrayReference(object obj, int idx, StackObject* objRef, IType t, IList mStack) { var nT = t.TypeForCLR; LoadFromArrayReference(obj, idx, objRef, nT, mStack); } void LoadFromArrayReference(object obj, int idx, StackObject* objRef, Type nT, IList mStack) { if (nT.IsPrimitive) { if (nT == typeof(int)) { int[] arr = obj as int[]; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = arr[idx]; objRef->ValueLow = 0; } else if (nT == typeof(short)) { short[] arr = obj as short[]; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = arr[idx]; objRef->ValueLow = 0; } else if (nT == typeof(long)) { long[] arr = obj as long[]; objRef->ObjectType = ObjectTypes.Long; *(long*)&objRef->Value = arr[idx]; objRef->ValueLow = 0; } else if (nT == typeof(float)) { float[] arr = obj as float[]; objRef->ObjectType = ObjectTypes.Float; *(float*)&objRef->Value = arr[idx]; objRef->ValueLow = 0; } else if (nT == typeof(double)) { double[] arr = obj as double[]; objRef->ObjectType = ObjectTypes.Double; *(double*)&objRef->Value = arr[idx]; objRef->ValueLow = 0; } else if (nT == typeof(byte)) { byte[] arr = obj as byte[]; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = arr[idx]; objRef->ValueLow = 0; } else if (nT == typeof(char)) { char[] arr = obj as char[]; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = arr[idx]; objRef->ValueLow = 0; } else if (nT == typeof(uint)) { uint[] arr = obj as uint[]; objRef->ObjectType = ObjectTypes.Integer; *(uint*)&objRef->Value = arr[idx]; objRef->ValueLow = 0; } else if (nT == typeof(sbyte)) { sbyte[] arr = obj as sbyte[]; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = arr[idx]; objRef->ValueLow = 0; } else throw new NotImplementedException(); } else { Array arr = obj as Array; objRef->ObjectType = ObjectTypes.Object; objRef->Value = mStack.Count; mStack.Add(arr.GetValue(idx)); objRef->ValueLow = 0; } } void StoreValueToArrayReference(StackObject* objRef, StackObject* val, IType t, IList mStack) { var nT = t.TypeForCLR; StoreValueToArrayReference(objRef, val, nT, mStack); } void StoreValueToArrayReference(StackObject* objRef, StackObject* val, Type nT, IList mStack) { if (nT.IsPrimitive) { if (nT == typeof(int)) { int[] arr = mStack[objRef->Value] as int[]; arr[objRef->ValueLow] = val->Value; } else if (nT == typeof(short)) { short[] arr = mStack[objRef->Value] as short[]; arr[objRef->ValueLow] = (short)val->Value; } else if (nT == typeof(long)) { long[] arr = mStack[objRef->Value] as long[]; arr[objRef->ValueLow] = *(long*)&val->Value; } else if (nT == typeof(float)) { float[] arr = mStack[objRef->Value] as float[]; arr[objRef->ValueLow] = *(float*)&val->Value; } else if (nT == typeof(double)) { double[] arr = mStack[objRef->Value] as double[]; arr[objRef->ValueLow] = *(double*)&val->Value; } else if (nT == typeof(byte)) { byte[] arr = mStack[objRef->Value] as byte[]; arr[objRef->ValueLow] = (byte)val->Value; } else if (nT == typeof(char)) { char[] arr = mStack[objRef->Value] as char[]; arr[objRef->ValueLow] = (char)val->Value; } else if (nT == typeof(uint)) { uint[] arr = mStack[objRef->Value] as uint[]; arr[objRef->ValueLow] = (uint)val->Value; } else if (nT == typeof(sbyte)) { sbyte[] arr = mStack[objRef->Value] as sbyte[]; arr[objRef->ValueLow] = (sbyte)val->Value; } else throw new NotImplementedException(); } else { Array arr = mStack[objRef->Value] as Array; arr.SetValue(mStack[val->Value], objRef->ValueLow); } } bool CheckExceptionType(IType catchType, object exception, bool explicitMatch) { if (catchType is CLRType) { if (explicitMatch) return exception.GetType() == catchType.TypeForCLR; else return catchType.TypeForCLR.IsAssignableFrom(exception.GetType()); } else throw new NotImplementedException(); } public static StackObject* GetObjectAndResolveReference(StackObject* esp) { if (esp->ObjectType == ObjectTypes.StackObjectReference) { return *(StackObject**)&esp->Value; } else return esp; } StackObject* PushParameters(IMethod method, StackObject* esp, object[] p) { IList mStack = stack.ManagedStack; var plist = method.Parameters; int pCnt = plist != null ? plist.Count : 0; int pCnt2 = p != null ? p.Length : 0; if (pCnt != pCnt2) throw new ArgumentOutOfRangeException("Parameter mismatch"); if (pCnt2 > 0) { for (int i = 0; i < p.Length; i++) { bool isBox = false; if (plist != null && i < plist.Count) isBox = plist[i] == AppDomain.ObjectType; object obj = p[i]; if (obj is CrossBindingAdaptorType) obj = ((CrossBindingAdaptorType)obj).ILInstance; esp = ILIntepreter.PushObject(esp, mStack, obj, isBox); } } return esp; } public void CopyToStack(StackObject* dst, StackObject* src, IList mStack) { *dst = *src; if (dst->ObjectType >= ObjectTypes.Object) { dst->Value = mStack.Count; var obj = mStack[src->Value]; mStack.Add(obj); } } internal static object CheckAndCloneValueType(object obj, Enviorment.AppDomain domain) { if (obj != null) { if (obj is ILTypeInstance) { ILTypeInstance ins = obj as ILTypeInstance; if (ins.IsValueType) { return ins.Clone(); } } else { var type = obj.GetType(); var typeFlags = type.GetTypeFlags(); var isPrimitive = (typeFlags & CLR.Utils.Extensions.TypeFlags.IsPrimitive) != 0; var isValueType = (typeFlags & CLR.Utils.Extensions.TypeFlags.IsValueType) != 0; if (!isPrimitive && isValueType) { var t = domain.GetType(type); return ((CLRType)t).PerformMemberwiseClone(obj); } } } return obj; } public static StackObject* PushOne(StackObject* esp) { esp->ObjectType = ObjectTypes.Integer; esp->Value = 1; return esp + 1; } public static StackObject* PushZero(StackObject* esp) { esp->ObjectType = ObjectTypes.Integer; esp->Value = 0; return esp + 1; } public static StackObject* PushNull(StackObject* esp) { esp->ObjectType = ObjectTypes.Null; esp->Value = -1; esp->ValueLow = 0; return esp + 1; } public static void UnboxObject(StackObject* esp, object obj) { if (obj is int) { esp->ObjectType = ObjectTypes.Integer; esp->Value = (int)obj; } else if (obj is bool) { esp->ObjectType = ObjectTypes.Integer; esp->Value = (bool)(obj) ? 1 : 0; } else if (obj is short) { esp->ObjectType = ObjectTypes.Integer; esp->Value = (short)obj; } else if (obj is long) { esp->ObjectType = ObjectTypes.Long; *(long*)(&esp->Value) = (long)obj; } else if (obj is float) { esp->ObjectType = ObjectTypes.Float; *(float*)(&esp->Value) = (float)obj; } else if (obj is byte) { esp->ObjectType = ObjectTypes.Integer; esp->Value = (byte)obj; } else if (obj is uint) { esp->ObjectType = ObjectTypes.Integer; esp->Value = (int)(uint)obj; } else if (obj is ushort) { esp->ObjectType = ObjectTypes.Integer; esp->Value = (int)(ushort)obj; } else if (obj is char) { esp->ObjectType = ObjectTypes.Integer; esp->Value = (int)(char)obj; } else if (obj is double) { esp->ObjectType = ObjectTypes.Double; *(double*)(&esp->Value) = (double)obj; } else if (obj is ulong) { esp->ObjectType = ObjectTypes.Long; *(ulong*)(&esp->Value) = (ulong)obj; } else if (obj is sbyte) { esp->ObjectType = ObjectTypes.Integer; esp->Value = (sbyte)obj; } else throw new NotImplementedException(); } public static StackObject* PushObject(StackObject* esp, IList mStack, object obj, bool isBox = false) { if (obj != null) { if (!isBox) { var typeFlags = obj.GetType().GetTypeFlags(); if ((typeFlags & CLR.Utils.Extensions.TypeFlags.IsPrimitive) != 0) { UnboxObject(esp, obj); } else if ((typeFlags & CLR.Utils.Extensions.TypeFlags.IsEnum) != 0) { esp->ObjectType = ObjectTypes.Integer; esp->Value = Convert.ToInt32(obj); } else { esp->ObjectType = ObjectTypes.Object; esp->Value = mStack.Count; mStack.Add(obj); } } else { esp->ObjectType = ObjectTypes.Object; esp->Value = mStack.Count; mStack.Add(obj); } } else { return PushNull(esp); } return esp + 1; } //Don't ask me why add this funky method for this, otherwise Unity won't calculate the right value public static StackObject* Add(StackObject* a, int b) { return (StackObject*)((long)a + sizeof(StackObject) * b); } public static StackObject* Minus(StackObject* a, int b) { return (StackObject*)((long)a - sizeof(StackObject) * b); } public void Free(StackObject* esp) { if (esp->ObjectType >= ObjectTypes.Object) { if (esp->Value == stack.ManagedStack.Count - 1) stack.ManagedStack.RemoveAt(esp->Value); } #if DEBUG esp->ObjectType = ObjectTypes.Null; esp->Value = -1; esp->ValueLow = 0; #endif } public void FreeStackValueType(StackObject* esp) { if (esp->ObjectType == ObjectTypes.ValueTypeObjectReference) { var addr = *(StackObject**)&esp->Value; if (addr <= ValueTypeBasePointer)//Only Stack allocation after base pointer should be freed, local variable are freed automatically stack.FreeValueTypeObject(esp); } } public void AllocValueType(StackObject* ptr, IType type) { stack.AllocValueType(ptr, type); } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Intepreter/ILRuntimeException.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.Runtime.Stack; namespace ILRuntime.Runtime.Intepreter { public class ILRuntimeException : Exception { string stackTrace; string thisInfo, localInfo; internal ILRuntimeException(string message, ILIntepreter intepreter, CLR.Method.ILMethod method, Exception innerException = null) : base(message, innerException) { var ds = intepreter.AppDomain.DebugService; if (innerException is ILRuntimeException) { ILRuntimeException e = innerException as ILRuntimeException; stackTrace = e.stackTrace; thisInfo = e.thisInfo; localInfo = e.localInfo; } else { stackTrace = ds.GetStackTrance(intepreter); if (method.HasThis) thisInfo = ds.GetThisInfo(intepreter); else thisInfo = ""; localInfo = ds.GetLocalVariableInfo(intepreter); } } public override string StackTrace { get { return stackTrace; } } public string ThisInfo { get { return thisInfo; } } public string LocalInfo { get { return localInfo; } } public override string ToString() { StringBuilder message = new StringBuilder(); message.AppendLine(Message); if (!string.IsNullOrEmpty(ThisInfo)) { message.AppendLine("this:"); message.AppendLine(ThisInfo); } message.AppendLine("Local Variables:"); message.AppendLine(LocalInfo); message.AppendLine(StackTrace); if (InnerException != null) message.AppendLine(InnerException.ToString()); return message.ToString(); } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Intepreter/ILTypeInstance.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.Utils; using ILRuntime.CLR.Method; using ILRuntime.CLR.TypeSystem; using ILRuntime.Runtime.Stack; namespace ILRuntime.Runtime.Intepreter { public class ILTypeStaticInstance : ILTypeInstance { public unsafe ILTypeStaticInstance(ILType type) { this.type = type; fields = new StackObject[type.StaticFieldTypes.Length]; managedObjs = new List(fields.Length); for (int i = 0; i < fields.Length; i++) { var ft = type.StaticFieldTypes[i]; var t = ft.TypeForCLR; managedObjs.Add(null); StackObject.Initialized(ref fields[i], i, t, ft, managedObjs); } int idx = 0; foreach (var i in type.TypeDefinition.Fields) { if (i.IsStatic) { if (i.InitialValue != null && i.InitialValue.Length > 0) { fields[idx].ObjectType = ObjectTypes.Object; managedObjs[idx] = i.InitialValue; } idx++; } } } } unsafe class ILEnumTypeInstance : ILTypeInstance { public ILEnumTypeInstance(ILType type) { if (!type.IsEnum) throw new NotSupportedException(); this.type = type; fields = new StackObject[1]; } public override string ToString() { var fields = type.TypeDefinition.Fields; long longVal = 0; int intVal = 0; bool isLong = this.fields[0].ObjectType == ObjectTypes.Long; if (isLong) { fixed (StackObject* f = this.fields) longVal = *(long*)&f->Value; } else intVal = this.fields[0].Value; for (int i = 0; i < fields.Count; i++) { var f = fields[i]; if (f.IsStatic) { if (isLong) { long val = f.Constant is long ? (long)f.Constant : (long)(ulong)f.Constant; if (val == longVal) return f.Name; } else { if (f.Constant is int) { if ((int)f.Constant == intVal) return f.Name; } else if (f.Constant is short) { if ((short)f.Constant == intVal) return f.Name; } else if (f.Constant is byte) { if ((byte)f.Constant == intVal) return f.Name; } else throw new NotImplementedException(); } } } return isLong ? longVal.ToString() : intVal.ToString(); } } public class ILTypeInstance { protected ILType type; protected StackObject[] fields; protected IList managedObjs; object clrInstance; Dictionary delegates; public ILType Type { get { return type; } } public StackObject[] Fields { get { return fields; } } public virtual bool IsValueType { get { return type.IsValueType && !Boxed; } } /// /// 是否已装箱 /// public bool Boxed { get; set; } public IList ManagedObjects { get { return managedObjs; } } public object CLRInstance { get { return clrInstance; } set { clrInstance = value; } } protected ILTypeInstance() { } public ILTypeInstance(ILType type, bool initializeCLRInstance = true) { this.type = type; fields = new StackObject[type.TotalFieldCount]; managedObjs = new List(fields.Length); for (int i = 0; i < fields.Length; i++) { managedObjs.Add(null); } InitializeFields(type); if (initializeCLRInstance) { if (type.FirstCLRBaseType is Enviorment.CrossBindingAdaptor) { clrInstance = ((Enviorment.CrossBindingAdaptor)type.FirstCLRBaseType).CreateCLRInstance(type.AppDomain, this); } else { clrInstance = this; } if(type.FirstCLRInterface is Enviorment.CrossBindingAdaptor) { if (clrInstance != this)//Only one CLRInstance is allowed atm, so implementing multiple interfaces is not supported { throw new NotSupportedException("Inheriting and implementing interface at the same time is not supported yet"); } clrInstance = ((Enviorment.CrossBindingAdaptor)type.FirstCLRInterface).CreateCLRInstance(type.AppDomain, this); } } else clrInstance = this; } public unsafe object this[int index] { get { if (index < fields.Length && index >= 0) { fixed (StackObject* ptr = fields) { StackObject* esp = &ptr[index]; return StackObject.ToObject(esp, null, managedObjs); } } else { if (Type.FirstCLRBaseType != null && Type.FirstCLRBaseType is Enviorment.CrossBindingAdaptor) { CLRType clrType = type.AppDomain.GetType(((Enviorment.CrossBindingAdaptor)Type.FirstCLRBaseType).BaseCLRType) as CLRType; return clrType.GetFieldValue(index, clrInstance); } else throw new TypeLoadException(); } } set { value = ILIntepreter.CheckAndCloneValueType(value, type.AppDomain); if (index < fields.Length && index >= 0) { fixed (StackObject* ptr = fields) { StackObject* esp = &ptr[index]; if (value != null) { if (value.GetType().IsPrimitive) { ILIntepreter.UnboxObject(esp, value); } else { esp->ObjectType = ObjectTypes.Object; esp->Value = index; managedObjs[index] = value; } } else *esp = StackObject.Null; } } else { if (Type.FirstCLRBaseType != null && Type.FirstCLRBaseType is Enviorment.CrossBindingAdaptor) { CLRType clrType = type.AppDomain.GetType(((Enviorment.CrossBindingAdaptor)Type.FirstCLRBaseType).BaseCLRType) as CLRType; clrType.SetFieldValue(index, ref clrInstance, value); } else throw new TypeLoadException(); } } } void InitializeFields(ILType type) { for (int i = 0; i < type.FieldTypes.Length; i++) { var ft = type.FieldTypes[i]; StackObject.Initialized(ref fields[type.FieldStartIndex + i], type.FieldStartIndex + i, ft.TypeForCLR, ft, managedObjs); } if (type.BaseType != null && type.BaseType is ILType) InitializeFields((ILType)type.BaseType); } internal unsafe void PushFieldAddress(int fieldIdx, StackObject* esp, IList managedStack) { esp->ObjectType = ObjectTypes.FieldReference; esp->Value = managedStack.Count; managedStack.Add(this); esp->ValueLow = fieldIdx; } internal unsafe void PushToStack(int fieldIdx, StackObject* esp, Enviorment.AppDomain appdomain, IList managedStack) { if (fieldIdx < fields.Length && fieldIdx >= 0) PushToStackSub(ref fields[fieldIdx], fieldIdx, esp, managedStack); else { if (Type.FirstCLRBaseType != null && Type.FirstCLRBaseType is Enviorment.CrossBindingAdaptor) { CLRType clrType = appdomain.GetType(((Enviorment.CrossBindingAdaptor)Type.FirstCLRBaseType).BaseCLRType) as CLRType; ILIntepreter.PushObject(esp, managedStack, clrType.GetFieldValue(fieldIdx, clrInstance)); } else throw new TypeLoadException(); } } unsafe void PushToStackSub(ref StackObject field, int fieldIdx, StackObject* esp, IList managedStack) { *esp = field; if (field.ObjectType >= ObjectTypes.Object) { esp->Value = managedStack.Count; managedStack.Add(managedObjs[fieldIdx]); } } internal unsafe void CopyValueTypeToStack(StackObject* ptr, IList mStack) { ptr->ObjectType = ObjectTypes.ValueTypeDescriptor; ptr->Value = type.GetHashCode(); ptr->ValueLow = type.TotalFieldCount; for(int i = 0; i < fields.Length; i++) { var val = ILIntepreter.Minus(ptr, i + 1); switch (val->ObjectType) { case ObjectTypes.Object: case ObjectTypes.FieldReference: case ObjectTypes.ArrayReference: mStack[val->Value] = managedObjs[i]; val->ValueLow = fields[i].ValueLow; break; case ObjectTypes.ValueTypeObjectReference: { var obj = managedObjs[i]; var dst = *(StackObject**)&val->Value; var vt = type.AppDomain.GetType(dst->Value); if (vt is ILType) { ((ILTypeInstance)obj).CopyValueTypeToStack(dst, mStack); } else { ((CLRType)vt).ValueTypeBinder.CopyValueTypeToStack(obj, dst, mStack); } } break; default: *val = fields[i]; break; } } } internal void Clear() { InitializeFields(type); } internal unsafe void AssignFromStack(int fieldIdx, StackObject* esp, Enviorment.AppDomain appdomain, IList managedStack) { if (fieldIdx < fields.Length && fieldIdx >= 0) AssignFromStackSub(ref fields[fieldIdx], fieldIdx, esp, managedStack); else { if (Type.FirstCLRBaseType != null && Type.FirstCLRBaseType is Enviorment.CrossBindingAdaptor) { CLRType clrType = appdomain.GetType(((Enviorment.CrossBindingAdaptor)Type.FirstCLRBaseType).BaseCLRType) as CLRType; var field = clrType.GetField(fieldIdx); clrType.SetFieldValue(fieldIdx, ref clrInstance, field.FieldType.CheckCLRTypes(ILIntepreter.CheckAndCloneValueType(StackObject.ToObject(esp, appdomain, managedStack), appdomain))); } else throw new TypeLoadException(); } } internal unsafe void AssignFromStack(StackObject* esp, Enviorment.AppDomain appdomain, IList managedStack) { StackObject* val = *(StackObject**)&esp->Value; int cnt = val->ValueLow; for (int i = 0; i < cnt; i++) { var addr = ILIntepreter.Minus(val, i + 1); AssignFromStack(i, addr, type.AppDomain, managedStack); } } unsafe void AssignFromStackSub(ref StackObject field, int fieldIdx, StackObject* esp, IList managedStack) { esp = ILIntepreter.GetObjectAndResolveReference(esp); field = *esp; switch (field.ObjectType) { case ObjectTypes.Object: case ObjectTypes.ArrayReference: case ObjectTypes.FieldReference: field.Value = fieldIdx; managedObjs[fieldIdx] = ILIntepreter.CheckAndCloneValueType(managedStack[esp->Value], Type.AppDomain); break; case ObjectTypes.ValueTypeObjectReference: { var domain = type.AppDomain; field.ObjectType = ObjectTypes.Object; field.Value = fieldIdx; var dst = *(StackObject**)&esp->Value; var vt = domain.GetType(dst->Value); if(vt is ILType) { var ins = managedObjs[fieldIdx]; if (ins == null) throw new NullReferenceException(); ILTypeInstance child = (ILTypeInstance)ins; child.AssignFromStack(esp, domain, managedStack); } else { managedObjs[fieldIdx] = ((CLRType)vt).ValueTypeBinder.ToObject(dst, managedStack); } } break; default: if (managedObjs != null) managedObjs[fieldIdx] = null; break; } } public override string ToString() { IMethod m = type.AppDomain.ObjectType.GetMethod("ToString", 0); m = type.GetVirtualMethod(m); if (m != null) { if (m is ILMethod) { var res = type.AppDomain.Invoke(m, this, null); return res.ToString(); } else return clrInstance.ToString(); } else return type.FullName; } public bool CanAssignTo(IType type) { return this.type.CanAssignTo(type); } public ILTypeInstance Clone() { ILTypeInstance ins = new ILTypeInstance(type); for (int i = 0; i < fields.Length; i++) { ins.fields[i] = fields[i]; ins.managedObjs[i] = managedObjs[i]; } if (type.FirstCLRBaseType is Enviorment.CrossBindingAdaptor) { ins.clrInstance = ((Enviorment.CrossBindingAdaptor)type.FirstCLRBaseType).CreateCLRInstance(type.AppDomain, ins); } else { ins.clrInstance = ins; } return ins; } internal IDelegateAdapter GetDelegateAdapter(ILMethod method) { if (delegates == null) delegates = new Dictionary(); IDelegateAdapter res; if (delegates.TryGetValue(method, out res)) return res; return null; } internal void SetDelegateAdapter(ILMethod method, IDelegateAdapter adapter) { if (!delegates.ContainsKey(method)) delegates[method] = adapter; else throw new NotSupportedException(); } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Intepreter/OpCodes/OpCode.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.Method; namespace ILRuntime.Runtime.Intepreter.OpCodes { /// /// IL指令 /// struct OpCode { /// /// 当前指令 /// public OpCodeEnum Code; /// /// Int32 操作数 /// public int TokenInteger; /// /// Int64 操作数 /// public long TokenLong; } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Intepreter/OpCodes/OpCodeEnum.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Intepreter.OpCodes { enum OpCodeEnum { /// /// 如果修补操作码,则填充空间。尽管可能消耗处理周期,但未执行任何有意义的操作。 /// Nop, /// /// 向公共语言结构 (CLI) 发出信号以通知调试器已撞上了一个断点。 /// Break, /// /// 将索引为 0 的参数加载到计算堆栈上。 /// Ldarg_0, /// /// 将索引为 1 的参数加载到计算堆栈上。 /// Ldarg_1, /// /// 将索引为 2 的参数加载到计算堆栈上。 /// Ldarg_2, /// /// 将索引为 3 的参数加载到计算堆栈上。 /// Ldarg_3, /// /// 将索引 0 处的局部变量加载到计算堆栈上。 /// Ldloc_0, /// /// 将索引 1 处的局部变量加载到计算堆栈上。 /// Ldloc_1, /// /// 将索引 2 处的局部变量加载到计算堆栈上。 /// Ldloc_2, /// /// 将索引 3 处的局部变量加载到计算堆栈上。 /// Ldloc_3, /// /// 从计算堆栈的顶部弹出当前值并将其存储到索引 0 处的局部变量列表中。 /// Stloc_0, /// /// 从计算堆栈的顶部弹出当前值并将其存储到索引 1 处的局部变量列表中。 /// Stloc_1, /// /// 从计算堆栈的顶部弹出当前值并将其存储到索引 2 处的局部变量列表中。 /// Stloc_2, /// /// 从计算堆栈的顶部弹出当前值并将其存储到索引 3 处的局部变量列表中。 /// Stloc_3, /// /// 将参数(由指定的短格式索引引用)加载到计算堆栈上。 /// Ldarg_S, /// /// 以短格式将参数地址加载到计算堆栈上。 /// Ldarga_S, /// /// 将位于计算堆栈顶部的值存储在参数槽中的指定索引处(短格式)。 /// Starg_S, /// /// 将特定索引处的局部变量加载到计算堆栈上(短格式)。 /// Ldloc_S, /// /// 将位于特定索引处的局部变量的地址加载到计算堆栈上(短格式)。 /// Ldloca_S, /// /// 从计算堆栈的顶部弹出当前值并将其存储在局部变量列表中的 index 处(短格式)。 /// Stloc_S, /// /// 将空引用(O 类型)推送到计算堆栈上。 /// Ldnull, /// /// 将整数值 -1 作为 int32 推送到计算堆栈上。 /// Ldc_I4_M1, /// /// 将整数值 0 作为 int32 推送到计算堆栈上。 /// Ldc_I4_0, /// /// 将整数值 1 作为 int32 推送到计算堆栈上。 /// Ldc_I4_1, /// /// 将整数值 2 作为 int32 推送到计算堆栈上。 /// Ldc_I4_2, /// /// 将整数值 3 作为 int32 推送到计算堆栈上。 /// Ldc_I4_3, /// /// 将整数值 4 作为 int32 推送到计算堆栈上。 /// Ldc_I4_4, /// /// 将整数值 5 作为 int32 推送到计算堆栈上。 /// Ldc_I4_5, /// /// 将整数值 6 作为 int32 推送到计算堆栈上。 /// Ldc_I4_6, /// /// 将整数值 7 作为 int32 推送到计算堆栈上。 /// Ldc_I4_7, /// /// 将整数值 8 作为 int32 推送到计算堆栈上。 /// Ldc_I4_8, /// /// 将提供的 int8 值作为 int32 推送到计算堆栈上(短格式)。 /// Ldc_I4_S, /// /// 将所提供的 int32 类型的值作为 int32 推送到计算堆栈上。 /// Ldc_I4, /// /// 将所提供的 int64 类型的值作为 int64 推送到计算堆栈上。 /// Ldc_I8, /// /// 将所提供的 float32 类型的值作为 F (float) 类型推送到计算堆栈上。 /// Ldc_R4, /// /// 将所提供的 float64 类型的值作为 F (float) 类型推送到计算堆栈上。 /// Ldc_R8, /// /// 复制计算堆栈上当前最顶端的值,然后将副本推送到计算堆栈上。 /// Dup, /// /// 移除当前位于计算堆栈顶部的值。 /// Pop, /// /// 退出当前方法并跳至指定方法。 /// Jmp, /// /// 调用由传递的方法说明符指示的方法。 /// Call, /// /// 通过调用约定描述的参数调用在计算堆栈上指示的方法(作为指向入口点的指针)。 /// Calli, /// /// 从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。 /// Ret, /// /// 无条件地将控制转移到目标指令(短格式)。 /// Br_S, /// /// 如果 value 为 false、空引用或零,则将控制转移到目标指令。 /// Brfalse_S, /// /// 如果 value 为 true、非空或非零,则将控制转移到目标指令(短格式)。 /// Brtrue_S, /// /// 如果两个值相等,则将控制转移到目标指令(短格式)。 /// Beq_S, /// /// 如果第一个值大于或等于第二个值,则将控制转移到目标指令(短格式)。 /// Bge_S, /// /// 如果第一个值大于第二个值,则将控制转移到目标指令(短格式)。 /// Bgt_S, /// /// 如果第一个值小于或等于第二个值,则将控制转移到目标指令(短格式)。 /// Ble_S, /// /// 如果第一个值小于第二个值,则将控制转移到目标指令(短格式)。 /// Blt_S, /// /// 当两个无符号整数值或不可排序的浮点型值不相等时,将控制转移到目标指令(短格式)。 /// Bne_Un_S, /// /// 当比较无符号整数值或不可排序的浮点型值时,如果第一个值大于第二个值,则将控制转移到目标指令(短格式)。 /// Bge_Un_S, /// /// 当比较无符号整数值或不可排序的浮点型值时,如果第一个值大于第二个值,则将控制转移到目标指令(短格式)。 /// Bgt_Un_S, /// /// 当比较无符号整数值或不可排序的浮点值时,如果第一个值小于或等于第二个值,则将控制权转移到目标指令(短格式)。 /// Ble_Un_S, /// /// 当比较无符号整数值或不可排序的浮点型值时,如果第一个值小于第二个值,则将控制转移到目标指令(短格式)。 /// Blt_Un_S, /// /// 无条件地将控制转移到目标指令。 /// Br, /// /// 如果 value 为 false、空引用(Visual Basic 中的 Nothing)或零,则将控制转移到目标指令。 /// Brfalse, /// /// 如果 value 为 true、非空或非零,则将控制转移到目标指令。 /// Brtrue, /// /// 如果两个值相等,则将控制转移到目标指令。 /// Beq, /// /// 如果第一个值大于或等于第二个值,则将控制转移到目标指令。 /// Bge, /// /// 如果第一个值大于第二个值,则将控制转移到目标指令。 /// Bgt, /// /// 如果第一个值小于或等于第二个值,则将控制转移到目标指令。 /// Ble, /// /// 如果第一个值小于第二个值,则将控制转移到目标指令。 /// Blt, /// /// 当两个无符号整数值或不可排序的浮点型值不相等时,将控制转移到目标指令。 /// Bne_Un, /// /// 当比较无符号整数值或不可排序的浮点型值时,如果第一个值大于第二个值,则将控制转移到目标指令。 /// Bge_Un, /// /// 当比较无符号整数值或不可排序的浮点型值时,如果第一个值大于第二个值,则将控制转移到目标指令。 /// Bgt_Un, /// /// 当比较无符号整数值或不可排序的浮点型值时,如果第一个值小于或等于第二个值,则将控制转移到目标指令。 /// Ble_Un, /// /// 当比较无符号整数值或不可排序的浮点型值时,如果第一个值小于第二个值,则将控制转移到目标指令。 /// Blt_Un, /// /// 实现跳转表。 /// Switch, /// /// 将 int8 类型的值作为 int32 间接加载到计算堆栈上。 /// Ldind_I1, /// /// 将 unsigned int8 类型的值作为 int32 间接加载到计算堆栈上。 /// Ldind_U1, /// /// 将 int16 类型的值作为 int32 间接加载到计算堆栈上。 /// Ldind_I2, /// /// 将 unsigned int16 类型的值作为 int32 间接加载到计算堆栈上。 /// Ldind_U2, /// /// 将 int32 类型的值作为 int32 间接加载到计算堆栈上。 /// Ldind_I4, /// /// 将 unsigned int32 类型的值作为 int32 间接加载到计算堆栈上。 /// Ldind_U4, /// /// 将 int64 类型的值作为 int64 间接加载到计算堆栈上。 /// Ldind_I8, /// /// 将 native int 类型的值作为 native int 间接加载到计算堆栈上。 /// Ldind_I, /// /// 将 float32 类型的值作为 F (float) 类型间接加载到计算堆栈上。 /// Ldind_R4, /// /// 将 float64 类型的值作为 F (float) 类型间接加载到计算堆栈上。 /// Ldind_R8, /// /// 将对象引用作为 O(对象引用)类型间接加载到计算堆栈上。 /// Ldind_Ref, /// /// 存储所提供地址处的对象引用值。 /// Stind_Ref, /// /// 在所提供的地址存储 int8 类型的值。 /// Stind_I1, /// /// 在所提供的地址存储 int16 类型的值。 /// Stind_I2, /// /// 在所提供的地址存储 int32 类型的值。 /// Stind_I4, /// /// 在所提供的地址存储 int64 类型的值。 /// Stind_I8, /// /// 在所提供的地址存储 float32 类型的值。 /// Stind_R4, /// /// 在所提供的地址存储 float64 类型的值。 /// Stind_R8, /// /// 将两个值相加并将结果推送到计算堆栈上。 /// Add, /// /// 从其他值中减去一个值并将结果推送到计算堆栈上。 /// Sub, /// /// 将两个值相乘并将结果推送到计算堆栈上。 /// Mul, /// /// 将两个值相除并将结果作为浮点(F 类型)或商(int32 类型)推送到计算堆栈上。 /// Div, /// /// 两个无符号整数值相除并将结果 ( int32 ) 推送到计算堆栈上。 /// Div_Un, /// /// 将两个值相除并将余数推送到计算堆栈上。 /// Rem, /// /// 将两个无符号值相除并将余数推送到计算堆栈上。 /// Rem_Un, /// /// 计算两个值的按位“与”并将结果推送到计算堆栈上。 /// And, /// /// 计算位于堆栈顶部的两个整数值的按位求补并将结果推送到计算堆栈上。 /// Or, /// /// 计算位于计算堆栈顶部的两个值的按位异或,并且将结果推送到计算堆栈上。 /// Xor, /// /// 将整数值左移(用零填充)指定的位数,并将结果推送到计算堆栈上。 /// Shl, /// /// 将整数值右移(保留符号)指定的位数,并将结果推送到计算堆栈上。 /// Shr, /// /// 将无符号整数值右移(用零填充)指定的位数,并将结果推送到计算堆栈上。 /// Shr_Un, /// /// 对一个值执行求反并将结果推送到计算堆栈上。 /// Neg, /// /// 计算堆栈顶部整数值的按位求补并将结果作为相同的类型推送到计算堆栈上。 /// Not, /// /// 将位于计算堆栈顶部的值转换为 int8,然后将其扩展(填充)为 int32。 /// Conv_I1, /// /// 将位于计算堆栈顶部的值转换为 int16,然后将其扩展(填充)为 int32。 /// Conv_I2, /// /// 将位于计算堆栈顶部的值转换为 int32。 /// Conv_I4, /// /// 将位于计算堆栈顶部的值转换为 int64。 /// Conv_I8, /// /// 将位于计算堆栈顶部的值转换为 float32。 /// Conv_R4, /// /// 将位于计算堆栈顶部的值转换为 float64。 /// Conv_R8, /// /// 将位于计算堆栈顶部的值转换为 unsigned int32,然后将其扩展为 int32。 /// Conv_U4, /// /// 将位于计算堆栈顶部的值转换为 unsigned int64,然后将其扩展为 int64。 /// Conv_U8, /// /// 对对象调用后期绑定方法,并且将返回值推送到计算堆栈上。 /// Callvirt, /// /// 将位于对象(&、* 或 native int 类型)地址的值类型复制到目标对象(&、* 或 native int 类型)的地址。 /// Cpobj, /// /// 将地址指向的值类型对象复制到计算堆栈的顶部。 /// Ldobj, /// /// 推送对元数据中存储的字符串的新对象引用。 /// Ldstr, /// /// 创建一个值类型的新对象或新实例,并将对象引用(O 类型)推送到计算堆栈上。 /// Newobj, /// /// 尝试将引用传递的对象转换为指定的类。 /// Castclass, /// /// 测试对象引用(O 类型)是否为特定类的实例。 /// Isinst, /// /// 将位于计算堆栈顶部的无符号整数值转换为 float32。 /// Conv_R_Un, /// /// 将值类型的已装箱的表示形式转换为其未装箱的形式。 /// Unbox, /// /// 引发当前位于计算堆栈上的异常对象。 /// Throw, /// /// 查找对象中其引用当前位于计算堆栈的字段的值。 /// Ldfld, /// /// 查找对象中其引用当前位于计算堆栈的字段的地址。 /// Ldflda, /// /// 用新值替换在对象引用或指针的字段中存储的值。 /// Stfld, /// /// 将静态字段的值推送到计算堆栈上。 /// Ldsfld, /// /// 将静态字段的地址推送到计算堆栈上。 /// Ldsflda, /// /// 用来自计算堆栈的值替换静态字段的值。 /// Stsfld, /// /// 将指定类型的值从计算堆栈复制到所提供的内存地址中。 /// Stobj, /// /// 将位于计算堆栈顶部的无符号值转换为有符号 int8 并将其扩展为 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_I1_Un, /// /// 将位于计算堆栈顶部的无符号值转换为有符号 int16 并将其扩展为 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_I2_Un, /// /// 将位于计算堆栈顶部的无符号值转换为有符号 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_I4_Un, /// /// 将位于计算堆栈顶部的无符号值转换为有符号 int64,并在溢出时引发 OverflowException。 /// Conv_Ovf_I8_Un, /// /// 将位于计算堆栈顶部的无符号值转换为 unsigned int8 并将其扩展为 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_U1_Un, /// /// 将位于计算堆栈顶部的无符号值转换为 unsigned int16 并将其扩展为 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_U2_Un, /// /// 将位于计算堆栈顶部的无符号值转换为 unsigned int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_U4_Un, /// /// 将位于计算堆栈顶部的无符号值转换为 unsigned int64,并在溢出时引发 OverflowException。 /// Conv_Ovf_U8_Un, /// /// 将位于计算堆栈顶部的无符号值转换为有符号 native int,并在溢出时引发 OverflowException。 /// Conv_Ovf_I_Un, /// /// 将位于计算堆栈顶部的无符号值转换为 unsigned native int,并在溢出时引发 OverflowException。 /// Conv_Ovf_U_Un, /// /// 将值类转换为对象引用(O 类型)。 /// Box, /// /// 将对新的从零开始的一维数组(其元素属于特定类型)的对象引用推送到计算堆栈上。 /// Newarr, /// /// 将从零开始的、一维数组的元素的数目推送到计算堆栈上。 /// Ldlen, /// /// 将位于指定数组索引的数组元素的地址作为 & 类型(托管指针)加载到计算堆栈的顶部。 /// Ldelema, /// /// 将位于指定数组索引处的 int8 类型的元素作为 int32 加载到计算堆栈的顶部。 /// Ldelem_I1, /// /// 将位于指定数组索引处的 unsigned int8 类型的元素作为 int32 加载到计算堆栈的顶部。 /// Ldelem_U1, /// /// 将位于指定数组索引处的 int16 类型的元素作为 int32 加载到计算堆栈的顶部。 /// Ldelem_I2, /// /// 将位于指定数组索引处的 unsigned int16 类型的元素作为 int32 加载到计算堆栈的顶部。 /// Ldelem_U2, /// /// 将位于指定数组索引处的 int32 类型的元素作为 int32 加载到计算堆栈的顶部。 /// Ldelem_I4, /// /// 将位于指定数组索引处的 unsigned int32 类型的元素作为 int32 加载到计算堆栈的顶部。 /// Ldelem_U4, /// /// 将位于指定数组索引处的 int64 类型的元素作为 int64 加载到计算堆栈的顶部。 /// Ldelem_I8, /// /// 将位于指定数组索引处的 native int 类型的元素作为 native int 加载到计算堆栈的顶部。 /// Ldelem_I, /// /// 将位于指定数组索引处的 float32 类型的元素作为 F 类型(浮点型)加载到计算堆栈的顶部。 /// Ldelem_R4, /// /// 将位于指定数组索引处的 float64 类型的元素作为 F 类型(浮点型)加载到计算堆栈的顶部。 /// Ldelem_R8, /// /// 将位于指定数组索引处的包含对象引用的元素作为 O 类型(对象引用)加载到计算堆栈的顶部。 /// Ldelem_Ref, /// /// 用计算堆栈上的 native int 值替换给定索引处的数组元素。 /// Stelem_I, /// /// 用计算堆栈上的 int8 值替换给定索引处的数组元素。 /// Stelem_I1, /// /// 用计算堆栈上的 int16 值替换给定索引处的数组元素。 /// Stelem_I2, /// /// 用计算堆栈上的 int32 值替换给定索引处的数组元素。 /// Stelem_I4, /// /// 用计算堆栈上的 int64 值替换给定索引处的数组元素。 /// Stelem_I8, /// /// 用计算堆栈上的 float32 值替换给定索引处的数组元素。 /// Stelem_R4, /// /// 用计算堆栈上的 float64 值替换给定索引处的数组元素。 /// Stelem_R8, /// /// 用计算堆栈上的对象 ref 值(O 类型)替换给定索引处的数组元素。 /// Stelem_Ref, /// /// 按照指令中指定的类型,将指定数组索引中的元素加载到计算堆栈的顶部。 /// Ldelem_Any, /// /// 用计算堆栈中的值替换给定索引处的数组元素,其类型在指令中指定。 /// Stelem_Any, /// /// 将指令中指定类型的已装箱的表示形式转换成未装箱形式。 /// Unbox_Any, /// /// 将位于计算堆栈顶部的有符号值转换为有符号 int8 并将其扩展为 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_I1, /// /// 将位于计算堆栈顶部的有符号值转换为 unsigned int8 并将其扩展为 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_U1, /// /// 将位于计算堆栈顶部的有符号值转换为有符号 int16 并将其扩展为 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_I2, /// /// 将位于计算堆栈顶部的有符号值转换为 unsigned int16 并将其扩展为 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_U2, /// /// 将位于计算堆栈顶部的有符号值转换为有符号 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_I4, /// /// 将位于计算堆栈顶部的有符号值转换为 unsigned int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_U4, /// /// 将位于计算堆栈顶部的有符号值转换为有符号 int64,并在溢出时引发 OverflowException。 /// Conv_Ovf_I8, /// /// 将位于计算堆栈顶部的有符号值转换为 unsigned int64,并在溢出时引发 OverflowException。 /// Conv_Ovf_U8, /// /// 检索嵌入在类型化引用内的地址(& 类型)。 /// Refanyval, /// /// 如果值不是有限数,则引发 ArithmeticException。 /// Ckfinite, /// /// 将对特定类型实例的类型化引用推送到计算堆栈上。 /// Mkrefany, /// /// 将元数据标记转换为其运行时表示形式,并将其推送到计算堆栈上。 /// Ldtoken, /// /// 将位于计算堆栈顶部的值转换为 unsigned int16,然后将其扩展为 int32。 /// Conv_U2, /// /// 将位于计算堆栈顶部的值转换为 unsigned int8,然后将其扩展为 int32。 /// Conv_U1, /// /// 将位于计算堆栈顶部的值转换为 native int。 /// Conv_I, /// /// 将位于计算堆栈顶部的有符号值转换为有符号 native int,并在溢出时引发 OverflowException。 /// Conv_Ovf_I, /// /// 将位于计算堆栈顶部的有符号值转换为 unsigned native int,并在溢出时引发 OverflowException。 /// Conv_Ovf_U, /// /// 将两个整数相加,执行溢出检查,并且将结果推送到计算堆栈上。 /// Add_Ovf, /// /// 将两个无符号整数值相加,执行溢出检查,并且将结果推送到计算堆栈上。 /// Add_Ovf_Un, /// /// 将两个整数值相乘,执行溢出检查,并将结果推送到计算堆栈上。 /// Mul_Ovf, /// /// 将两个无符号整数值相乘,执行溢出检查,并将结果推送到计算堆栈上。 /// Mul_Ovf_Un, /// /// 从另一值中减去一个整数值,执行溢出检查,并且将结果推送到计算堆栈上。 /// Sub_Ovf, /// /// 从另一值中减去一个无符号整数值,执行溢出检查,并且将结果推送到计算堆栈上。 /// Sub_Ovf_Un, /// /// 将控制从异常块的 fault 或 finally 子句转移回公共语言结构 (CLI) 异常处理程序。 /// Endfinally, /// /// 退出受保护的代码区域,无条件将控制转移到特定目标指令。 /// Leave, /// /// 退出受保护的代码区域,无条件将控制转移到目标指令(缩写形式)。 /// Leave_S, /// /// 在所提供的地址存储 native int 类型的值。 /// Stind_I, /// /// 将位于计算堆栈顶部的值转换为 unsigned native int,然后将其扩展为 native int。 /// Conv_U, /// /// 返回指向当前方法的参数列表的非托管指针。 /// Arglist, /// /// 比较两个值。如果这两个值相等,则将整数值 1 (int32) 推送到计算堆栈上;否则,将 0 (int32) 推送到计算堆栈上。 /// Ceq, /// /// 比较两个值。如果第一个值大于第二个值,则将整数值 1 (int32) 推送到计算堆栈上;反之,将 0 (int32) 推送到计算堆栈上。 /// Cgt, /// /// 比较两个无符号的或不可排序的值。如果第一个值大于第二个值,则将整数值 1 (int32) 推送到计算堆栈上;反之,将 0 (int32) 推送到计算堆栈上。 /// Cgt_Un, /// /// 比较两个值。如果第一个值小于第二个值,则将整数值 1 (int32) 推送到计算堆栈上;反之,将 0 (int32) 推送到计算堆栈上。 /// Clt, /// /// 比较无符号的或不可排序的值 value1 和 value2。如果 value1 小于 value2,则将整数值 1 (int32 ) 推送到计算堆栈上;反之,将 0 ( int32 ) 推送到计算堆栈上。 /// Clt_Un, /// /// 将指向实现特定方法的本机代码的非托管指针(native int 类型)推送到计算堆栈上。 /// Ldftn, /// /// 将指向实现与指定对象关联的特定虚方法的本机代码的非托管指针(native int 类型)推送到计算堆栈上。 /// Ldvirtftn, /// /// 将参数(由指定索引值引用)加载到堆栈上。 /// Ldarg, /// /// 将参数地址加载到计算堆栈上。 /// Ldarga, /// /// 将位于计算堆栈顶部的值存储到位于指定索引的参数槽中。 /// Starg, /// /// 将指定索引处的局部变量加载到计算堆栈上。 /// Ldloc, /// /// 将位于特定索引处的局部变量的地址加载到计算堆栈上。 /// Ldloca, /// /// 从计算堆栈的顶部弹出当前值并将其存储到指定索引处的局部变量列表中。 /// Stloc, /// /// 从本地动态内存池分配特定数目的字节并将第一个分配的字节的地址(瞬态指针,* 类型)推送到计算堆栈上。 /// Localloc, /// /// 将控制从异常的 filter 子句转移回公共语言结构 (CLI) 异常处理程序。 /// Endfilter, /// /// 指示当前位于计算堆栈上的地址可能没有与紧接的 ldind、stind、ldfld、stfld、ldobj、stobj、initblk 或 cpblk 指令的自然大小对齐。 /// Unaligned, /// /// 指定当前位于计算堆栈顶部的地址可以是易失的,并且读取该位置的结果不能被缓存,或者对该地址的多个存储区不能被取消。 /// Volatile, /// /// 执行后缀的方法调用指令,以便在执行实际调用指令前移除当前方法的堆栈帧。 /// Tail, /// /// 将位于指定地址的值类型的每个字段初始化为空引用或适当的基元类型的 0。 /// Initobj, /// /// 约束要对其进行虚方法调用的类型。 /// Constrained, /// /// 将指定数目的字节从源地址复制到目标地址。 /// Cpblk, /// /// 将位于特定地址的内存的指定块初始化为给定大小和初始值。 /// Initblk, No, /// /// 再次引发当前异常。 /// Rethrow, /// /// 将提供的值类型的大小(以字节为单位)推送到计算堆栈上。 /// Sizeof, /// /// 检索嵌入在类型化引用内的类型标记。 /// Refanytype, /// /// 指定后面的数组地址操作在运行时不执行类型检查,并且返回可变性受限的托管指针。 /// Readonly, } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Stack/RuntimeStack.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.Method; using ILRuntime.CLR.TypeSystem; using ILRuntime.Other; using ILRuntime.Runtime.Intepreter; namespace ILRuntime.Runtime.Stack { unsafe public class RuntimeStack : IDisposable { ILIntepreter intepreter; StackObject* pointer; StackObject* endOfMemory; StackObject* valueTypePtr; IntPtr nativePointer; #if DEBUG IList managedStack = new List(32); #else IList managedStack = new UncheckedList(32); #endif Stack frames = new Stack(); const int MAXIMAL_STACK_OBJECTS = 1024 * 16; public Stack Frames { get { return frames; } } public RuntimeStack(ILIntepreter intepreter) { this.intepreter = intepreter; nativePointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(sizeof(StackObject) * MAXIMAL_STACK_OBJECTS); pointer = (StackObject*)nativePointer.ToPointer(); endOfMemory = Add(pointer, MAXIMAL_STACK_OBJECTS); valueTypePtr = endOfMemory - 1; } ~RuntimeStack() { Dispose(); } public StackObject* StackBase { get { return pointer; } } public StackObject* ValueTypeStackPointer { get { return valueTypePtr; } } public StackObject* ValueTypeStackBase { get { return endOfMemory - 1; } } public IList ManagedStack { get { return managedStack; } } public void ResetValueTypePointer() { valueTypePtr = endOfMemory - 1; } public void InitializeFrame(ILMethod method, StackObject* esp, out StackFrame res) { if (esp < pointer || esp >= endOfMemory) throw new StackOverflowException(); if (frames.Count > 0 && frames.Peek().BasePointer > esp) throw new StackOverflowException(); res = new StackFrame(); res.LocalVarPointer = esp; res.Method = method; #if DEBUG res.Address = new IntegerReference(); for (int i = 0; i < method.LocalVariableCount; i++) { var p = Add(esp, i); p->ObjectType = ObjectTypes.Null; } #endif res.BasePointer = method.LocalVariableCount > 0 ? Add(esp, method.LocalVariableCount + 1) : esp; res.ManagedStackBase = managedStack.Count; res.ValueTypeBasePointer = valueTypePtr; //frames.Push(res); } public void PushFrame(ref StackFrame frame) { frames.Push(frame); } public StackObject* PopFrame(ref StackFrame frame, StackObject* esp) { if (frames.Count > 0 && frames.Peek().BasePointer == frame.BasePointer) frames.Pop(); else throw new NotSupportedException(); StackObject* returnVal = esp - 1; var method = frame.Method; StackObject* ret = ILIntepreter.Minus(frame.LocalVarPointer, method.ParameterCount); int mStackBase = frame.ManagedStackBase; if (method.HasThis) ret--; if(method.ReturnType != intepreter.AppDomain.VoidType) { *ret = *returnVal; if(ret->ObjectType == ObjectTypes.Object) { ret->Value = mStackBase; managedStack[mStackBase] = managedStack[returnVal->Value]; mStackBase++; } else if(ret->ObjectType == ObjectTypes.ValueTypeObjectReference) { StackObject* oriAddr = frame.ValueTypeBasePointer; RelocateValueType(ret, ref frame.ValueTypeBasePointer, ref mStackBase); *(StackObject**)&ret->Value = oriAddr; } ret++; } #if DEBUG ((List)managedStack).RemoveRange(mStackBase, managedStack.Count - mStackBase); #else ((UncheckedList)managedStack).RemoveRange(mStackBase, managedStack.Count - mStackBase); #endif valueTypePtr = frame.ValueTypeBasePointer; return ret; } void RelocateValueType(StackObject* src, ref StackObject* dst, ref int mStackBase) { StackObject* descriptor = *(StackObject**)&src->Value; if (descriptor > dst) throw new StackOverflowException(); *dst = *descriptor; int cnt = descriptor->ValueLow; StackObject* endAddr = ILIntepreter.Minus(dst, cnt + 1); for(int i = 0; i < cnt; i++) { StackObject* addr = ILIntepreter.Minus(descriptor, i + 1); StackObject* tarVal = ILIntepreter.Minus(dst, i + 1); *tarVal = *addr; switch (addr->ObjectType) { case ObjectTypes.Object: case ObjectTypes.ArrayReference: case ObjectTypes.FieldReference: if (tarVal->Value >= mStackBase) { int oldIdx = addr->Value; tarVal->Value = mStackBase; managedStack[mStackBase] = managedStack[oldIdx]; mStackBase++; } break; case ObjectTypes.ValueTypeObjectReference: var newAddr = endAddr; RelocateValueType(addr, ref endAddr, ref mStackBase); *(StackObject**)&tarVal->Value = newAddr; break; } } dst = endAddr; } public void AllocValueType(StackObject* ptr, IType type) { if (type.IsValueType) { int fieldCount = 0; if(type is ILType) { fieldCount = ((ILType)type).TotalFieldCount; } else { fieldCount = ((CLRType)type).TotalFieldCount; } ptr->ObjectType = ObjectTypes.ValueTypeObjectReference; var dst = valueTypePtr; *(StackObject**)&ptr->Value = dst; dst->ObjectType = ObjectTypes.ValueTypeDescriptor; dst->Value = type.GetHashCode(); dst->ValueLow = fieldCount; valueTypePtr = ILIntepreter.Minus(valueTypePtr, fieldCount + 1); if (valueTypePtr <= StackBase) throw new StackOverflowException(); InitializeValueTypeObject(type, dst); } else throw new ArgumentException(type.FullName + " is not a value type.", "type"); } void InitializeValueTypeObject(IType type, StackObject* ptr) { if (type is ILType) { ILType t = (ILType)type; for (int i = 0; i < t.FieldTypes.Length; i++) { var ft = t.FieldTypes[i]; StackObject* val = ILIntepreter.Minus(ptr, t.FieldStartIndex + i + 1); if (ft.IsPrimitive) StackObject.Initialized(val, ft); else { if (ft.IsValueType) { AllocValueType(val, ft); } else { val->ObjectType = ObjectTypes.Object; val->Value = managedStack.Count; managedStack.Add(null); } } } if (type.BaseType != null && type.BaseType is ILType) InitializeValueTypeObject((ILType)type.BaseType, ptr); } else { CLRType t = (CLRType)type; var cnt = t.TotalFieldCount; for(int i = 0; i < cnt; i++) { var it = t.OrderedFieldTypes[i] as CLRType; StackObject* val = ILIntepreter.Minus(ptr, i + 1); if (it.IsPrimitive) StackObject.Initialized(val, it); else { if (it.IsValueType) { if (it.ValueTypeBinder != null) AllocValueType(val, it); else { val->ObjectType = ObjectTypes.Object; val->Value = managedStack.Count; managedStack.Add(it.CreateDefaultInstance()); } } else { val->ObjectType = ObjectTypes.Object; val->Value = managedStack.Count; managedStack.Add(null); } } } } } public void ClearValueTypeObject(IType type, StackObject* ptr) { if (type is ILType) { ILType t = (ILType)type; for (int i = 0; i < t.FieldTypes.Length; i++) { var ft = t.FieldTypes[i]; StackObject* val = ILIntepreter.Minus(ptr, t.FieldStartIndex + i + 1); if (ft.IsPrimitive) StackObject.Initialized(val, ft); else { switch (val->ObjectType) { case ObjectTypes.ValueTypeObjectReference: ClearValueTypeObject(ft, *(StackObject**)&val->Value); break; default: if (ft.IsValueType) { if(ft is ILType) { throw new NotImplementedException(); } else { managedStack[val->Value] = ((CLRType)ft).CreateDefaultInstance(); } } else managedStack[val->Value] = null; break; } } } if (type.BaseType != null && type.BaseType is ILType) ClearValueTypeObject((ILType)type.BaseType, ptr); } else { CLRType t = (CLRType)type; var cnt = t.TotalFieldCount; for (int i = 0; i < cnt; i++) { var vt = t.OrderedFieldTypes[i] as CLRType; StackObject* val = ILIntepreter.Minus(ptr, i + 1); if (vt.IsPrimitive) StackObject.Initialized(val, vt); else { switch (val->ObjectType) { case ObjectTypes.ValueTypeObjectReference: { var dst = *(StackObject**)&val->Value; ClearValueTypeObject(vt, *(StackObject**)&val->Value); } break; default: if (vt.IsValueType) { managedStack[val->Value] = vt.CreateDefaultInstance(); } else managedStack[val->Value] = null; break; } } } } } public void FreeValueTypeObject(StackObject* esp) { int start = int.MaxValue; int end = int.MinValue; StackObject* endAddr; CountValueTypeManaged(esp, ref start, ref end, &endAddr); if (endAddr == valueTypePtr) valueTypePtr = *(StackObject**)&esp->Value; else throw new NotSupportedException(); if (start != int.MaxValue) { if (end == managedStack.Count - 1) { #if DEBUG ((List)managedStack).RemoveRange(start, managedStack.Count - start); #else ((UncheckedList)managedStack).RemoveRange(start, managedStack.Count - start); #endif } else throw new NotSupportedException(); } } void CountValueTypeManaged(StackObject* esp, ref int start, ref int end, StackObject** endAddr) { StackObject* descriptor = *(StackObject**)&esp->Value; int cnt = descriptor->ValueLow; *endAddr = ILIntepreter.Minus(descriptor, cnt + 1); for (int i = 0; i < cnt; i++) { StackObject* addr = ILIntepreter.Minus(descriptor, i + 1); switch (addr->ObjectType) { case ObjectTypes.Object: case ObjectTypes.ArrayReference: case ObjectTypes.FieldReference: { if (start == int.MaxValue) { start = addr->Value; end = start; } else if (addr->Value == end + 1) end++; else throw new NotSupportedException(); } break; case ObjectTypes.ValueTypeObjectReference: CountValueTypeManaged(addr, ref start, ref end, endAddr); break; } } } public void Dispose() { if (nativePointer != IntPtr.Zero) { System.Runtime.InteropServices.Marshal.FreeHGlobal(nativePointer); nativePointer = IntPtr.Zero; } } StackObject* Add(StackObject* a, int b) { return (StackObject*)((long)a + sizeof(StackObject) * b); } } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Stack/StackFrame.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.Method; namespace ILRuntime.Runtime.Stack { public class IntegerReference { public int Value { get; set; } } unsafe public struct StackFrame { public ILMethod Method; public StackObject* LocalVarPointer; public StackObject* BasePointer; public StackObject* ValueTypeBasePointer; public IntegerReference Address; public int ManagedStackBase; } } ================================================ FILE: ILRuntime/ILRuntime/Runtime/Stack/StackObject.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.TypeSystem; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; namespace ILRuntime.Runtime.Stack { [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] public struct StackObject { public static StackObject Null = new StackObject() { ObjectType = ObjectTypes.Null, Value = -1, ValueLow = 0 }; public ObjectTypes ObjectType; public int Value; public int ValueLow; //IL2CPP can't process esp->ToObject() properly, so I can only use static function for this public static unsafe object ToObject(StackObject* esp, ILRuntime.Runtime.Enviorment.AppDomain appdomain, IList mStack) { switch (esp->ObjectType) { case ObjectTypes.Integer: return esp->Value; case ObjectTypes.Long: { return *(long*)&esp->Value; } case ObjectTypes.Float: { return *(float*)&esp->Value; } case ObjectTypes.Double: { return *(double*)&esp->Value; } case ObjectTypes.Object: return mStack[esp->Value]; case ObjectTypes.FieldReference: { ILTypeInstance instance = mStack[esp->Value] as ILTypeInstance; if (instance != null) { return instance[esp->ValueLow]; } else { var obj = mStack[esp->Value]; IType t = null; if (obj is CrossBindingAdaptorType) { t = appdomain.GetType(((CrossBindingAdaptor)((CrossBindingAdaptorType)obj).ILInstance.Type.FirstCLRBaseType).BaseCLRType); } else t = appdomain.GetType(obj.GetType()); return ((CLRType)t).GetFieldValue(esp->ValueLow, obj); } } case ObjectTypes.ArrayReference: { Array instance = mStack[esp->Value] as Array; return instance.GetValue(esp->ValueLow); } case ObjectTypes.StaticFieldReference: { var t = appdomain.GetType(esp->Value); if (t is CLR.TypeSystem.ILType) { CLR.TypeSystem.ILType type = (CLR.TypeSystem.ILType)t; return type.StaticInstance[esp->ValueLow]; } else { CLR.TypeSystem.CLRType type = (CLR.TypeSystem.CLRType)t; return type.GetFieldValue(esp->ValueLow, null); } } case ObjectTypes.StackObjectReference: { return ToObject((*(StackObject**)&esp->Value), appdomain, mStack); } case ObjectTypes.ValueTypeObjectReference: { StackObject* dst = *(StackObject**)&esp->Value; IType type = appdomain.GetType(dst->Value); if (type is ILType) { ILType iltype = (ILType)type; var ins = iltype.Instantiate(false); for (int i = 0; i < dst->ValueLow; i++) { var addr = ILIntepreter.Minus(dst, i + 1); ins.AssignFromStack(i, addr, appdomain, mStack); } return ins; } else { return ((CLRType)type).ValueTypeBinder.ToObject(dst, mStack); } } case ObjectTypes.Null: return null; default: throw new NotImplementedException(); } } public unsafe static void Initialized(ref StackObject esp, int idx, Type t, IType fieldType, IList mStack) { if (t.IsPrimitive) { if (t == typeof(int) || t == typeof(uint) || t == typeof(short) || t == typeof(ushort) || t == typeof(byte) || t == typeof(sbyte) || t == typeof(char) || t == typeof(bool)) { esp.ObjectType = ObjectTypes.Integer; esp.Value = 0; esp.ValueLow = 0; } else if (t == typeof(long) || t == typeof(ulong)) { esp.ObjectType = ObjectTypes.Long; esp.Value = 0; esp.ValueLow = 0; } else if (t == typeof(float)) { esp.ObjectType = ObjectTypes.Float; esp.Value = 0; esp.ValueLow = 0; } else if (t == typeof(double)) { esp.ObjectType = ObjectTypes.Double; esp.Value = 0; esp.ValueLow = 0; } else throw new NotImplementedException(); } else { if (fieldType.IsValueType) { esp.ObjectType = ObjectTypes.Object; esp.Value = idx; if (fieldType is CLRType) { mStack[idx] = ((CLRType)fieldType).CreateDefaultInstance(); } else { mStack[idx] = ((ILType)fieldType).Instantiate(); } } else esp = Null; } } //IL2CPP can't process esp->Initialized() properly, so I can only use static function for this public unsafe static void Initialized(StackObject* esp, IType type) { var t = type.TypeForCLR; if (type.IsPrimitive) { if (t == typeof(int) || t == typeof(uint) || t == typeof(short) || t == typeof(ushort) || t == typeof(byte) || t == typeof(sbyte) || t == typeof(char) || t == typeof(bool)) { esp->ObjectType = ObjectTypes.Integer; esp->Value = 0; esp->ValueLow = 0; } else if (t == typeof(long) || t == typeof(ulong)) { esp->ObjectType = ObjectTypes.Long; esp->Value = 0; esp->ValueLow = 0; } else if (t == typeof(float)) { esp->ObjectType = ObjectTypes.Float; esp->Value = 0; esp->ValueLow = 0; } else if (t == typeof(double)) { esp->ObjectType = ObjectTypes.Double; esp->Value = 0; esp->ValueLow = 0; } else throw new NotImplementedException(); } else { *esp = Null; } } } public enum ObjectTypes { Null, Integer, Long, Float, Double, StackObjectReference,//Value = pointer, StaticFieldReference, ValueTypeObjectReference, ValueTypeDescriptor, Object, FieldReference,//Value = objIdx, ValueLow = fieldIdx ArrayReference,//Value = objIdx, ValueLow = elemIdx } } ================================================ FILE: ILRuntime/ILRuntime.csproj ================================================  Debug AnyCPU {0887056B-2D5E-4FBE-9F15-EFF3E2612CA7} Library ILRuntime ILRuntime v3.5 512 true AnyCPU true full false ..\Libs\ DEBUG;TRACE prompt 0 false true AnyCPU pdbonly true ..\Libs\ TRACE prompt 0 false true $(ProjectDir)..\Libs\PublishLibrary.bat $(TargetName) ================================================ FILE: ILRuntime/ILRuntime.csproj.user ================================================  ProjectFiles ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono/Actions.cs ================================================ // // Actions.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // #if !NET_3_5 && !NET_4_0 namespace Mono { //delegate void Action (); delegate void Action (T1 arg1, T2 arg2); //delegate void Action (T1 arg1, T2 arg2, T3 arg3); //delegate void Action (T1 arg1, T2 arg2, T3 arg3, T4 arg4); } #endif ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono/Empty.cs ================================================ // // Empty.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using Mono.Collections.Generic; namespace Mono { static class Empty { public static readonly T [] Array = new T [0]; } } namespace Mono.Cecil { static partial class Mixin { public static bool IsNullOrEmpty (T [] self) { return self == null || self.Length == 0; } public static bool IsNullOrEmpty (Collection self) { return self == null || self.size == 0; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono/Funcs.cs ================================================ // // Funcs.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // #if !NET_3_5 && !NET_4_0 namespace Mono { delegate TResult Func (); delegate TResult Func (T arg1); delegate TResult Func (T1 arg1, T2 arg2); //delegate TResult Func (T1 arg1, T2 arg2, T3 arg3); //delegate TResult Func (T1 arg1, T2 arg2, T3 arg3, T4 arg4); } #endif ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/ArrayType.cs ================================================ // // ArrayType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Text; using Mono.Collections.Generic; using MD = Mono.Cecil.Metadata; namespace Mono.Cecil { public struct ArrayDimension { int? lower_bound; int? upper_bound; public int? LowerBound { get { return lower_bound; } set { lower_bound = value; } } public int? UpperBound { get { return upper_bound; } set { upper_bound = value; } } public bool IsSized { get { return lower_bound.HasValue || upper_bound.HasValue; } } public ArrayDimension (int? lowerBound, int? upperBound) { this.lower_bound = lowerBound; this.upper_bound = upperBound; } public override string ToString () { return !IsSized ? string.Empty : lower_bound + "..." + upper_bound; } } public sealed class ArrayType : TypeSpecification { Collection dimensions; public Collection Dimensions { get { if (dimensions != null) return dimensions; dimensions = new Collection (); dimensions.Add (new ArrayDimension ()); return dimensions; } } public int Rank { get { return dimensions == null ? 1 : dimensions.Count; } } public bool IsVector { get { if (dimensions == null) return true; if (dimensions.Count > 1) return false; var dimension = dimensions [0]; return !dimension.IsSized; } } public override bool IsValueType { get { return false; } set { throw new InvalidOperationException (); } } public override string Name { get { return base.Name + Suffix; } } public override string FullName { get { return base.FullName + Suffix; } } string Suffix { get { if (IsVector) return "[]"; var suffix = new StringBuilder (); suffix.Append ("["); for (int i = 0; i < dimensions.Count; i++) { if (i > 0) suffix.Append (","); suffix.Append (dimensions [i].ToString ()); } suffix.Append ("]"); return suffix.ToString (); } } public override bool IsArray { get { return true; } } public ArrayType (TypeReference type) : base (type) { Mixin.CheckType (type); this.etype = MD.ElementType.Array; } public ArrayType (TypeReference type, int rank) : this (type) { Mixin.CheckType (type); if (rank == 1) return; dimensions = new Collection (rank); for (int i = 0; i < rank; i++) dimensions.Add (new ArrayDimension ()); this.etype = MD.ElementType.Array; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/AssemblyDefinition.cs ================================================ // // AssemblyDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.IO; using Mono.Collections.Generic; namespace Mono.Cecil { public sealed class AssemblyDefinition : ICustomAttributeProvider, ISecurityDeclarationProvider { AssemblyNameDefinition name; internal ModuleDefinition main_module; Collection modules; Collection custom_attributes; Collection security_declarations; public AssemblyNameDefinition Name { get { return name; } set { name = value; } } public string FullName { get { return name != null ? name.FullName : string.Empty; } } public MetadataToken MetadataToken { get { return new MetadataToken(TokenType.Assembly, 1); } set { } } public Collection Modules { get { if (modules != null) return modules; if (main_module.HasImage) return main_module.Read(ref modules, this, (_, reader) => reader.ReadModules()); return modules = new Collection(1) { main_module }; } } public ModuleDefinition MainModule { get { return main_module; } } public MethodDefinition EntryPoint { get { return main_module.EntryPoint; } set { main_module.EntryPoint = value; } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return Mixin.GetHasCustomAttributes(this, main_module); } } public Collection CustomAttributes { get { return custom_attributes ?? (Mixin.GetCustomAttributes(this, ref custom_attributes, main_module)); } } public bool HasSecurityDeclarations { get { if (security_declarations != null) return security_declarations.Count > 0; return Mixin.GetHasSecurityDeclarations(this, main_module); } } public Collection SecurityDeclarations { get { return security_declarations ?? (Mixin.GetSecurityDeclarations(this, ref security_declarations, main_module)); } } internal AssemblyDefinition() { } public static AssemblyDefinition ReadAssembly(string fileName) { return ReadAssembly(ModuleDefinition.ReadModule(fileName)); } public static AssemblyDefinition ReadAssembly(string fileName, ReaderParameters parameters) { return ReadAssembly(ModuleDefinition.ReadModule(fileName, parameters)); } public static AssemblyDefinition ReadAssembly(Stream stream) { return ReadAssembly(ModuleDefinition.ReadModule(stream)); } public static AssemblyDefinition ReadAssembly(Stream stream, ReaderParameters parameters) { return ReadAssembly(ModuleDefinition.ReadModule(stream, parameters)); } static AssemblyDefinition ReadAssembly(ModuleDefinition module) { var assembly = module.Assembly; if (assembly == null) throw new ArgumentException(); return assembly; } public override string ToString() { return this.FullName; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/AssemblyFlags.cs ================================================ // // AssemblyFlags.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum AssemblyAttributes : uint { PublicKey = 0x0001, SideBySideCompatible = 0x0000, Retargetable = 0x0100, WindowsRuntime = 0x0200, DisableJITCompileOptimizer = 0x4000, EnableJITCompileTracking = 0x8000, } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/AssemblyHashAlgorithm.cs ================================================ // // AssemblyHashAlgorithm.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public enum AssemblyHashAlgorithm : uint { None = 0x0000, Reserved = 0x8003, // MD5 SHA1 = 0x8004 } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/AssemblyLinkedResource.cs ================================================ // // AssemblyLinkedResource.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { public sealed class AssemblyLinkedResource : Resource { AssemblyNameReference reference; public AssemblyNameReference Assembly { get { return reference; } set { reference = value; } } public override ResourceType ResourceType { get { return ResourceType.AssemblyLinked; } } public AssemblyLinkedResource (string name, ManifestResourceAttributes flags) : base (name, flags) { } public AssemblyLinkedResource (string name, ManifestResourceAttributes flags, AssemblyNameReference reference) : base (name, flags) { this.reference = reference; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/AssemblyNameDefinition.cs ================================================ // // AssemblyNameDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { public sealed class AssemblyNameDefinition : AssemblyNameReference { public override byte [] Hash { get { return Empty.Array; } } internal AssemblyNameDefinition () { this.token = new MetadataToken (TokenType.Assembly, 1); } public AssemblyNameDefinition (string name, Version version) : base (name, version) { this.token = new MetadataToken (TokenType.Assembly, 1); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/AssemblyNameReference.cs ================================================ // // AssemblyNameReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Globalization; using System.Security.Cryptography; using System.Text; namespace Mono.Cecil { public class AssemblyNameReference : IMetadataScope { string name; string culture; Version version; uint attributes; byte[] public_key; byte[] public_key_token; AssemblyHashAlgorithm hash_algorithm; byte[] hash; internal MetadataToken token; string full_name; public string Name { get { return name; } set { name = value; full_name = null; } } public string Culture { get { return culture; } set { culture = value; full_name = null; } } public Version Version { get { return version; } set { version = value; full_name = null; } } public AssemblyAttributes Attributes { get { return (AssemblyAttributes)attributes; } set { attributes = (uint)value; } } public bool HasPublicKey { get { return Mixin.GetAttributes(attributes,(uint)AssemblyAttributes.PublicKey); } set { attributes =Mixin.SetAttributes(attributes,(uint)AssemblyAttributes.PublicKey, value); } } public bool IsSideBySideCompatible { get { return Mixin.GetAttributes(attributes,(uint)AssemblyAttributes.SideBySideCompatible); } set { attributes =Mixin.SetAttributes(attributes,(uint)AssemblyAttributes.SideBySideCompatible, value); } } public bool IsRetargetable { get { return Mixin.GetAttributes(attributes,(uint)AssemblyAttributes.Retargetable); } set { attributes =Mixin.SetAttributes(attributes,(uint)AssemblyAttributes.Retargetable, value); } } public bool IsWindowsRuntime { get { return Mixin.GetAttributes(attributes,(uint)AssemblyAttributes.WindowsRuntime); } set { attributes =Mixin.SetAttributes(attributes,(uint)AssemblyAttributes.WindowsRuntime, value); } } public byte[] PublicKey { get { return public_key ?? Empty.Array; } set { public_key = value; HasPublicKey = !Mixin.IsNullOrEmpty(public_key); public_key_token = Empty.Array; full_name = null; } } public byte[] PublicKeyToken { get { if (Mixin.IsNullOrEmpty(public_key_token) && !Mixin.IsNullOrEmpty(public_key)) { var hash = HashPublicKey(); // we need the last 8 bytes in reverse order byte[] local_public_key_token = new byte[8]; Array.Copy(hash, (hash.Length - 8), local_public_key_token, 0, 8); Array.Reverse(local_public_key_token, 0, 8); public_key_token = local_public_key_token; // publish only once finished (required for thread-safety) } return public_key_token ?? Empty.Array; } set { public_key_token = value; full_name = null; } } byte[] HashPublicKey() { HashAlgorithm algorithm; switch (hash_algorithm) { case AssemblyHashAlgorithm.Reserved: throw new NotSupportedException(); default: // None default to SHA1 algorithm = new SHA1Managed(); break; } using (algorithm) return algorithm.ComputeHash(public_key); } public virtual MetadataScopeType MetadataScopeType { get { return MetadataScopeType.AssemblyNameReference; } } public string FullName { get { if (full_name != null) return full_name; const string sep = ", "; var builder = new StringBuilder(); builder.Append(name); if (version != null) { builder.Append(sep); builder.Append("Version="); builder.Append(version.ToString()); } builder.Append(sep); builder.Append("Culture="); builder.Append(string.IsNullOrEmpty(culture) ? "neutral" : culture); builder.Append(sep); builder.Append("PublicKeyToken="); var pk_token = PublicKeyToken; if (!Mixin.IsNullOrEmpty(pk_token) && pk_token.Length > 0) { for (int i = 0; i < pk_token.Length; i++) { builder.Append(pk_token[i].ToString("x2")); } } else builder.Append("null"); return full_name = builder.ToString(); } } public static AssemblyNameReference Parse(string fullName) { if (fullName == null) throw new ArgumentNullException("fullName"); if (fullName.Length == 0) throw new ArgumentException("Name can not be empty"); var name = new AssemblyNameReference(); var tokens = fullName.Split(','); for (int i = 0; i < tokens.Length; i++) { var token = tokens[i].Trim(); if (i == 0) { name.Name = token; continue; } var parts = token.Split('='); if (parts.Length != 2) throw new ArgumentException("Malformed name"); switch (parts[0].ToLowerInvariant()) { case "version": name.Version = new Version(parts[1]); break; case "culture": name.Culture = parts[1]; break; case "publickeytoken": var pk_token = parts[1]; if (pk_token == "null") break; name.PublicKeyToken = new byte[pk_token.Length / 2]; for (int j = 0; j < name.PublicKeyToken.Length; j++) name.PublicKeyToken[j] = Byte.Parse(pk_token.Substring(j * 2, 2), NumberStyles.HexNumber); break; } } return name; } public AssemblyHashAlgorithm HashAlgorithm { get { return hash_algorithm; } set { hash_algorithm = value; } } public virtual byte[] Hash { get { return hash; } set { hash = value; } } public MetadataToken MetadataToken { get { return token; } set { token = value; } } internal AssemblyNameReference() { } public AssemblyNameReference(string name, Version version) { if (name == null) throw new ArgumentNullException("name"); this.name = name; this.version = version; this.hash_algorithm = AssemblyHashAlgorithm.None; this.token = new MetadataToken(TokenType.AssemblyRef); } public override string ToString() { return this.FullName; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/AssemblyReader.cs ================================================ // // AssemblyReader.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using System.IO; using System.Text; using Mono.Collections.Generic; using Mono.Cecil.Cil; using Mono.Cecil.Metadata; using Mono.Cecil.PE; using RVA = System.UInt32; namespace Mono.Cecil { abstract class ModuleReader { readonly protected Image image; readonly protected ModuleDefinition module; protected ModuleReader(Image image, ReadingMode mode) { this.image = image; this.module = new ModuleDefinition(image); this.module.ReadingMode = mode; } protected abstract void ReadModule(); protected void ReadModuleManifest(MetadataReader reader) { reader.Populate(module); ReadAssembly(reader); } void ReadAssembly(MetadataReader reader) { var name = reader.ReadAssemblyNameDefinition(); if (name == null) { module.kind = ModuleKind.NetModule; return; } var assembly = new AssemblyDefinition(); assembly.Name = name; module.assembly = assembly; assembly.main_module = module; } public static ModuleDefinition CreateModuleFrom(Image image, ReaderParameters parameters) { var module = ReadModule(image, parameters); ReadSymbols(module, parameters); if (parameters.AssemblyResolver != null) module.assembly_resolver = parameters.AssemblyResolver; if (parameters.MetadataResolver != null) module.metadata_resolver = parameters.MetadataResolver; return module; } static void ReadSymbols(ModuleDefinition module, ReaderParameters parameters) { var symbol_reader_provider = parameters.SymbolReaderProvider; if (symbol_reader_provider == null && parameters.ReadSymbols) symbol_reader_provider = SymbolProvider.GetPlatformReaderProvider(); if (symbol_reader_provider != null) { module.SymbolReaderProvider = symbol_reader_provider; var reader = parameters.SymbolStream != null ? symbol_reader_provider.GetSymbolReader(module, parameters.SymbolStream) : symbol_reader_provider.GetSymbolReader(module, module.FullyQualifiedName); module.ReadSymbols(reader); } } static ModuleDefinition ReadModule(Image image, ReaderParameters parameters) { var reader = CreateModuleReader(image, parameters.ReadingMode); reader.ReadModule(); return reader.module; } static ModuleReader CreateModuleReader(Image image, ReadingMode mode) { switch (mode) { case ReadingMode.Immediate: return new ImmediateModuleReader(image); case ReadingMode.Deferred: return new DeferredModuleReader(image); default: throw new ArgumentException(); } } } sealed class ImmediateModuleReader : ModuleReader { public ImmediateModuleReader(Image image) : base(image, ReadingMode.Immediate) { } protected override void ReadModule() { this.module.Read(this.module, (module, reader) => { ReadModuleManifest(reader); ReadModule(module); return module; }); } public static void ReadModule(ModuleDefinition module) { if (module.HasAssemblyReferences) Read(module.AssemblyReferences); if (module.HasResources) Read(module.Resources); if (module.HasModuleReferences) Read(module.ModuleReferences); if (module.HasTypes) ReadTypes(module.Types); if (module.HasExportedTypes) Read(module.ExportedTypes); if (module.HasCustomAttributes) Read(module.CustomAttributes); var assembly = module.Assembly; if (assembly == null) return; if (assembly.HasCustomAttributes) Read(assembly.CustomAttributes); if (assembly.HasSecurityDeclarations) Read(assembly.SecurityDeclarations); } static void ReadTypes(Collection types) { for (int i = 0; i < types.Count; i++) ReadType(types[i]); } static void ReadType(TypeDefinition type) { ReadGenericParameters(type); if (type.HasInterfaces) Read(type.Interfaces); if (type.HasNestedTypes) ReadTypes(type.NestedTypes); if (type.HasLayoutInfo) Read(type.ClassSize); if (type.HasFields) ReadFields(type); if (type.HasMethods) ReadMethods(type); if (type.HasProperties) ReadProperties(type); if (type.HasEvents) ReadEvents(type); ReadSecurityDeclarations(type); ReadCustomAttributes(type); } static void ReadGenericParameters(IGenericParameterProvider provider) { if (!provider.HasGenericParameters) return; var parameters = provider.GenericParameters; for (int i = 0; i < parameters.Count; i++) { var parameter = parameters[i]; if (parameter.HasConstraints) Read(parameter.Constraints); if (parameter.HasCustomAttributes) Read(parameter.CustomAttributes); } } static void ReadSecurityDeclarations(ISecurityDeclarationProvider provider) { if (provider.HasSecurityDeclarations) Read(provider.SecurityDeclarations); } static void ReadCustomAttributes(ICustomAttributeProvider provider) { if (provider.HasCustomAttributes) Read(provider.CustomAttributes); } static void ReadFields(TypeDefinition type) { var fields = type.Fields; for (int i = 0; i < fields.Count; i++) { var field = fields[i]; if (field.HasConstant) Read(field.Constant); if (field.HasLayoutInfo) Read(field.Offset); if (field.RVA > 0) Read(field.InitialValue); if (field.HasMarshalInfo) Read(field.MarshalInfo); ReadCustomAttributes(field); } } static void ReadMethods(TypeDefinition type) { var methods = type.Methods; for (int i = 0; i < methods.Count; i++) { var method = methods[i]; ReadGenericParameters(method); if (method.HasParameters) ReadParameters(method); if (method.HasOverrides) Read(method.Overrides); if (method.IsPInvokeImpl) Read(method.PInvokeInfo); ReadSecurityDeclarations(method); ReadCustomAttributes(method); var return_type = method.MethodReturnType; if (return_type.HasConstant) Read(return_type.Constant); if (return_type.HasMarshalInfo) Read(return_type.MarshalInfo); ReadCustomAttributes(return_type); } } static void ReadParameters(MethodDefinition method) { var parameters = method.Parameters; for (int i = 0; i < parameters.Count; i++) { var parameter = parameters[i]; if (parameter.HasConstant) Read(parameter.Constant); if (parameter.HasMarshalInfo) Read(parameter.MarshalInfo); ReadCustomAttributes(parameter); } } static void ReadProperties(TypeDefinition type) { var properties = type.Properties; for (int i = 0; i < properties.Count; i++) { var property = properties[i]; Read(property.GetMethod); if (property.HasConstant) Read(property.Constant); ReadCustomAttributes(property); } } static void ReadEvents(TypeDefinition type) { var events = type.Events; for (int i = 0; i < events.Count; i++) { var @event = events[i]; Read(@event.AddMethod); ReadCustomAttributes(@event); } } static void Read(object collection) { } } sealed class DeferredModuleReader : ModuleReader { public DeferredModuleReader(Image image) : base(image, ReadingMode.Deferred) { } protected override void ReadModule() { this.module.Read(this.module, (module, reader) => { ReadModuleManifest(reader); return module; }); } } sealed class MetadataReader : ByteBuffer { readonly internal Image image; readonly internal ModuleDefinition module; readonly internal MetadataSystem metadata; internal IGenericContext context; internal CodeReader code; uint Position { get { return (uint)base.position; } set { base.position = (int)value; } } public MetadataReader(ModuleDefinition module) : base(module.Image.MetadataSection.Data) { this.image = module.Image; this.module = module; this.metadata = module.MetadataSystem; this.code = new CodeReader(image.MetadataSection, this); } int GetCodedIndexSize(CodedIndex index) { return image.GetCodedIndexSize(index); } uint ReadByIndexSize(int size) { if (size == 4) return ReadUInt32(); else return ReadUInt16(); } byte[] ReadBlob() { var blob_heap = image.BlobHeap; if (blob_heap == null) { position += 2; return Empty.Array; } return blob_heap.Read(ReadBlobIndex()); } byte[] ReadBlob(uint signature) { var blob_heap = image.BlobHeap; if (blob_heap == null) return Empty.Array; return blob_heap.Read(signature); } uint ReadBlobIndex() { var blob_heap = image.BlobHeap; return ReadByIndexSize(blob_heap != null ? blob_heap.IndexSize : 2); } string ReadString() { return image.StringHeap.Read(ReadByIndexSize(image.StringHeap.IndexSize)); } uint ReadStringIndex() { return ReadByIndexSize(image.StringHeap.IndexSize); } uint ReadTableIndex(Table table) { return ReadByIndexSize(image.GetTableIndexSize(table)); } MetadataToken ReadMetadataToken(CodedIndex index) { return Mixin.GetMetadataToken(index, ReadByIndexSize(GetCodedIndexSize(index))); } int MoveTo(Table table) { var info = image.TableHeap[table]; if (info.Length != 0) Position = info.Offset; return (int)info.Length; } bool MoveTo(Table table, uint row) { var info = image.TableHeap[table]; var length = info.Length; if (length == 0 || row > length) return false; Position = info.Offset + (info.RowSize * (row - 1)); return true; } public AssemblyNameDefinition ReadAssemblyNameDefinition() { if (MoveTo(Table.Assembly) == 0) return null; var name = new AssemblyNameDefinition(); name.HashAlgorithm = (AssemblyHashAlgorithm)ReadUInt32(); PopulateVersionAndFlags(name); name.PublicKey = ReadBlob(); PopulateNameAndCulture(name); return name; } public ModuleDefinition Populate(ModuleDefinition module) { if (MoveTo(Table.Module) == 0) return module; Advance(2); // Generation module.Name = ReadString(); module.Mvid = image.GuidHeap.Read(ReadByIndexSize(image.GuidHeap.IndexSize)); return module; } void InitializeAssemblyReferences() { if (metadata.AssemblyReferences != null) return; int length = MoveTo(Table.AssemblyRef); var references = metadata.AssemblyReferences = new AssemblyNameReference[length]; for (uint i = 0; i < length; i++) { var reference = new AssemblyNameReference(); reference.token = new MetadataToken(TokenType.AssemblyRef, i + 1); PopulateVersionAndFlags(reference); var key_or_token = ReadBlob(); if (reference.HasPublicKey) reference.PublicKey = key_or_token; else reference.PublicKeyToken = key_or_token; PopulateNameAndCulture(reference); reference.Hash = ReadBlob(); references[i] = reference; } } public Collection ReadAssemblyReferences() { InitializeAssemblyReferences(); return new Collection(metadata.AssemblyReferences); } public MethodDefinition ReadEntryPoint() { if (module.Image.EntryPointToken == 0) return null; var token = new MetadataToken(module.Image.EntryPointToken); return GetMethodDefinition(token.RID); } public Collection ReadModules() { var modules = new Collection(1); modules.Add(this.module); int length = MoveTo(Table.File); for (uint i = 1; i <= length; i++) { var attributes = (FileAttributes)ReadUInt32(); var name = ReadString(); ReadBlobIndex(); if (attributes != FileAttributes.ContainsMetaData) continue; var parameters = new ReaderParameters { ReadingMode = module.ReadingMode, SymbolReaderProvider = module.SymbolReaderProvider, }; modules.Add(ModuleDefinition.ReadModule( GetModuleFileName(name), parameters)); } return modules; } string GetModuleFileName(string name) { if (module.FullyQualifiedName == null) throw new NotSupportedException(); var path = Path.GetDirectoryName(module.FullyQualifiedName); return Path.Combine(path, name); } void InitializeModuleReferences() { if (metadata.ModuleReferences != null) return; int length = MoveTo(Table.ModuleRef); var references = metadata.ModuleReferences = new ModuleReference[length]; for (uint i = 0; i < length; i++) { var reference = new ModuleReference(ReadString()); reference.token = new MetadataToken(TokenType.ModuleRef, i + 1); references[i] = reference; } } public Collection ReadModuleReferences() { InitializeModuleReferences(); return new Collection(metadata.ModuleReferences); } public bool HasFileResource() { int length = MoveTo(Table.File); if (length == 0) return false; for (uint i = 1; i <= length; i++) if (ReadFileRecord(i).Col1 == FileAttributes.ContainsNoMetaData) return true; return false; } public Collection ReadResources() { int length = MoveTo(Table.ManifestResource); var resources = new Collection(length); for (int i = 1; i <= length; i++) { var offset = ReadUInt32(); var flags = (ManifestResourceAttributes)ReadUInt32(); var name = ReadString(); var implementation = ReadMetadataToken(CodedIndex.Implementation); Resource resource; if (implementation.RID == 0) { resource = new EmbeddedResource(name, flags, offset, this); } else if (implementation.TokenType == TokenType.AssemblyRef) { resource = new AssemblyLinkedResource(name, flags) { Assembly = (AssemblyNameReference)GetTypeReferenceScope(implementation), }; } else if (implementation.TokenType == TokenType.File) { var file_record = ReadFileRecord(implementation.RID); resource = new LinkedResource(name, flags) { File = file_record.Col2, hash = ReadBlob(file_record.Col3) }; } else throw new NotSupportedException(); resources.Add(resource); } return resources; } Row ReadFileRecord(uint rid) { var position = this.position; if (!MoveTo(Table.File, rid)) throw new ArgumentException(); var record = new Row( (FileAttributes)ReadUInt32(), ReadString(), ReadBlobIndex()); this.position = position; return record; } public MemoryStream GetManagedResourceStream(uint offset) { var rva = image.Resources.VirtualAddress; var section = image.GetSectionAtVirtualAddress(rva); var position = (rva - section.VirtualAddress) + offset; var buffer = section.Data; var length = buffer[position] | (buffer[position + 1] << 8) | (buffer[position + 2] << 16) | (buffer[position + 3] << 24); return new MemoryStream(buffer, (int)position + 4, length); } void PopulateVersionAndFlags(AssemblyNameReference name) { name.Version = new Version( ReadUInt16(), ReadUInt16(), ReadUInt16(), ReadUInt16()); name.Attributes = (AssemblyAttributes)ReadUInt32(); } void PopulateNameAndCulture(AssemblyNameReference name) { name.Name = ReadString(); name.Culture = ReadString(); } public TypeDefinitionCollection ReadTypes() { InitializeTypeDefinitions(); var mtypes = metadata.Types; var type_count = mtypes.Length - metadata.NestedTypes.Count; var types = new TypeDefinitionCollection(module, type_count); for (int i = 0; i < mtypes.Length; i++) { var type = mtypes[i]; if (IsNested(type.Attributes)) continue; types.Add(type); } if (image.HasTable(Table.MethodPtr) || image.HasTable(Table.FieldPtr)) CompleteTypes(); return types; } void CompleteTypes() { var types = metadata.Types; for (int i = 0; i < types.Length; i++) { var type = types[i]; InitializeCollection(type.Fields); InitializeCollection(type.Methods); } } void InitializeTypeDefinitions() { if (metadata.Types != null) return; InitializeNestedTypes(); InitializeFields(); InitializeMethods(); int length = MoveTo(Table.TypeDef); var types = metadata.Types = new TypeDefinition[length]; for (uint i = 0; i < length; i++) { if (types[i] != null) continue; types[i] = ReadType(i + 1); } } static bool IsNested(TypeAttributes attributes) { switch (attributes & TypeAttributes.VisibilityMask) { case TypeAttributes.NestedAssembly: case TypeAttributes.NestedFamANDAssem: case TypeAttributes.NestedFamily: case TypeAttributes.NestedFamORAssem: case TypeAttributes.NestedPrivate: case TypeAttributes.NestedPublic: return true; default: return false; } } public bool HasNestedTypes(TypeDefinition type) { uint[] mapping; InitializeNestedTypes(); if (!metadata.TryGetNestedTypeMapping(type, out mapping)) return false; return mapping.Length > 0; } public Collection ReadNestedTypes(TypeDefinition type) { InitializeNestedTypes(); uint[] mapping; if (!metadata.TryGetNestedTypeMapping(type, out mapping)) return new MemberDefinitionCollection(type); var nested_types = new MemberDefinitionCollection(type, mapping.Length); for (int i = 0; i < mapping.Length; i++) { var nested_type = GetTypeDefinition(mapping[i]); if (nested_type != null) nested_types.Add(nested_type); } metadata.RemoveNestedTypeMapping(type); return nested_types; } void InitializeNestedTypes() { if (metadata.NestedTypes != null) return; var length = MoveTo(Table.NestedClass); metadata.NestedTypes = new Dictionary(length); metadata.ReverseNestedTypes = new Dictionary(length); if (length == 0) return; for (int i = 1; i <= length; i++) { var nested = ReadTableIndex(Table.TypeDef); var declaring = ReadTableIndex(Table.TypeDef); AddNestedMapping(declaring, nested); } } void AddNestedMapping(uint declaring, uint nested) { metadata.SetNestedTypeMapping(declaring, AddMapping(metadata.NestedTypes, declaring, nested)); metadata.SetReverseNestedTypeMapping(nested, declaring); } static TValue[] AddMapping(Dictionary cache, TKey key, TValue value) { TValue[] mapped; if (!cache.TryGetValue(key, out mapped)) { mapped = new[] { value }; return mapped; } var new_mapped = new TValue[mapped.Length + 1]; Array.Copy(mapped, new_mapped, mapped.Length); new_mapped[mapped.Length] = value; return new_mapped; } TypeDefinition ReadType(uint rid) { if (!MoveTo(Table.TypeDef, rid)) return null; var attributes = (TypeAttributes)ReadUInt32(); var name = ReadString(); var @namespace = ReadString(); var type = new TypeDefinition(@namespace, name, attributes); type.token = new MetadataToken(TokenType.TypeDef, rid); type.scope = module; type.module = module; metadata.AddTypeDefinition(type); this.context = type; type.BaseType = GetTypeDefOrRef(ReadMetadataToken(CodedIndex.TypeDefOrRef)); type.fields_range = ReadFieldsRange(rid); type.methods_range = ReadMethodsRange(rid); if (IsNested(attributes)) type.DeclaringType = GetNestedTypeDeclaringType(type); return type; } TypeDefinition GetNestedTypeDeclaringType(TypeDefinition type) { uint declaring_rid; if (!metadata.TryGetReverseNestedTypeMapping(type, out declaring_rid)) return null; metadata.RemoveReverseNestedTypeMapping(type); return GetTypeDefinition(declaring_rid); } Range ReadFieldsRange(uint type_index) { return ReadListRange(type_index, Table.TypeDef, Table.Field); } Range ReadMethodsRange(uint type_index) { return ReadListRange(type_index, Table.TypeDef, Table.Method); } Range ReadListRange(uint current_index, Table current, Table target) { var list = new Range(); list.Start = ReadTableIndex(target); uint next_index; var current_table = image.TableHeap[current]; if (current_index == current_table.Length) next_index = image.TableHeap[target].Length + 1; else { var position = Position; Position += (uint)(current_table.RowSize - image.GetTableIndexSize(target)); next_index = ReadTableIndex(target); Position = position; } list.Length = next_index - list.Start; return list; } public Row ReadTypeLayout(TypeDefinition type) { InitializeTypeLayouts(); Row class_layout; var rid = type.token.RID; if (!metadata.ClassLayouts.TryGetValue(rid, out class_layout)) return new Row(Mixin.NoDataMarker, Mixin.NoDataMarker); type.PackingSize = (short)class_layout.Col1; type.ClassSize = (int)class_layout.Col2; metadata.ClassLayouts.Remove(rid); return new Row((short)class_layout.Col1, (int)class_layout.Col2); } void InitializeTypeLayouts() { if (metadata.ClassLayouts != null) return; int length = MoveTo(Table.ClassLayout); var class_layouts = metadata.ClassLayouts = new Dictionary>(length); for (uint i = 0; i < length; i++) { var packing_size = ReadUInt16(); var class_size = ReadUInt32(); var parent = ReadTableIndex(Table.TypeDef); class_layouts.Add(parent, new Row(packing_size, class_size)); } } public TypeReference GetTypeDefOrRef(MetadataToken token) { return (TypeReference)LookupToken(token); } public TypeDefinition GetTypeDefinition(uint rid) { InitializeTypeDefinitions(); var type = metadata.GetTypeDefinition(rid); if (type != null) return type; return ReadTypeDefinition(rid); } TypeDefinition ReadTypeDefinition(uint rid) { if (!MoveTo(Table.TypeDef, rid)) return null; return ReadType(rid); } void InitializeTypeReferences() { if (metadata.TypeReferences != null) return; metadata.TypeReferences = new TypeReference[image.GetTableLength(Table.TypeRef)]; } public TypeReference GetTypeReference(string scope, string full_name) { InitializeTypeReferences(); var length = metadata.TypeReferences.Length; for (uint i = 1; i <= length; i++) { var type = GetTypeReference(i); if (type.FullName != full_name) continue; if (string.IsNullOrEmpty(scope)) return type; if (type.Scope.Name == scope) return type; } return null; } TypeReference GetTypeReference(uint rid) { InitializeTypeReferences(); var type = metadata.GetTypeReference(rid); if (type != null) return type; return ReadTypeReference(rid); } TypeReference ReadTypeReference(uint rid) { if (!MoveTo(Table.TypeRef, rid)) return null; TypeReference declaring_type = null; IMetadataScope scope; var scope_token = ReadMetadataToken(CodedIndex.ResolutionScope); var name = ReadString(); var @namespace = ReadString(); var type = new TypeReference( @namespace, name, module, null); type.token = new MetadataToken(TokenType.TypeRef, rid); metadata.AddTypeReference(type); if (scope_token.TokenType == TokenType.TypeRef) { declaring_type = GetTypeDefOrRef(scope_token); scope = declaring_type != null ? declaring_type.Scope : module; } else scope = GetTypeReferenceScope(scope_token); type.scope = scope; type.DeclaringType = declaring_type; MetadataSystem.TryProcessPrimitiveTypeReference(type); return type; } IMetadataScope GetTypeReferenceScope(MetadataToken scope) { switch (scope.TokenType) { case TokenType.AssemblyRef: InitializeAssemblyReferences(); return metadata.AssemblyReferences[(int)scope.RID - 1]; case TokenType.ModuleRef: InitializeModuleReferences(); return metadata.ModuleReferences[(int)scope.RID - 1]; case TokenType.Module: return module; default: throw new NotSupportedException(); } } public IEnumerable GetTypeReferences() { InitializeTypeReferences(); var length = image.GetTableLength(Table.TypeRef); var type_references = new TypeReference[length]; for (uint i = 1; i <= length; i++) type_references[i - 1] = GetTypeReference(i); return type_references; } TypeReference GetTypeSpecification(uint rid) { if (!MoveTo(Table.TypeSpec, rid)) return null; var reader = ReadSignature(ReadBlobIndex()); var type = reader.ReadTypeSignature(); if (type.token.RID == 0) type.token = new MetadataToken(TokenType.TypeSpec, rid); return type; } SignatureReader ReadSignature(uint signature) { return new SignatureReader(signature, this); } public bool HasInterfaces(TypeDefinition type) { InitializeInterfaces(); MetadataToken[] mapping; return metadata.TryGetInterfaceMapping(type, out mapping); } public Collection ReadInterfaces(TypeDefinition type) { InitializeInterfaces(); MetadataToken[] mapping; if (!metadata.TryGetInterfaceMapping(type, out mapping)) return new Collection(); var interfaces = new Collection(mapping.Length); this.context = type; for (int i = 0; i < mapping.Length; i++) interfaces.Add(GetTypeDefOrRef(mapping[i])); metadata.RemoveInterfaceMapping(type); return interfaces; } void InitializeInterfaces() { if (metadata.Interfaces != null) return; int length = MoveTo(Table.InterfaceImpl); metadata.Interfaces = new Dictionary(length); for (int i = 0; i < length; i++) { var type = ReadTableIndex(Table.TypeDef); var @interface = ReadMetadataToken(CodedIndex.TypeDefOrRef); AddInterfaceMapping(type, @interface); } } void AddInterfaceMapping(uint type, MetadataToken @interface) { metadata.SetInterfaceMapping(type, AddMapping(metadata.Interfaces, type, @interface)); } public Collection ReadFields(TypeDefinition type) { var fields_range = type.fields_range; if (fields_range.Length == 0) return new MemberDefinitionCollection(type); var fields = new MemberDefinitionCollection(type, (int)fields_range.Length); this.context = type; if (!MoveTo(Table.FieldPtr, fields_range.Start)) { if (!MoveTo(Table.Field, fields_range.Start)) return fields; for (uint i = 0; i < fields_range.Length; i++) ReadField(fields_range.Start + i, fields); } else ReadPointers(Table.FieldPtr, Table.Field, fields_range, fields, ReadField); return fields; } void ReadField(uint field_rid, Collection fields) { var attributes = (FieldAttributes)ReadUInt16(); var name = ReadString(); var signature = ReadBlobIndex(); var field = new FieldDefinition(name, attributes, ReadFieldType(signature)); field.token = new MetadataToken(TokenType.Field, field_rid); metadata.AddFieldDefinition(field); if (IsDeleted(field)) return; fields.Add(field); } void InitializeFields() { if (metadata.Fields != null) return; metadata.Fields = new FieldDefinition[image.GetTableLength(Table.Field)]; } TypeReference ReadFieldType(uint signature) { var reader = ReadSignature(signature); const byte field_sig = 0x6; if (reader.ReadByte() != field_sig) throw new NotSupportedException(); return reader.ReadTypeSignature(); } public int ReadFieldRVA(FieldDefinition field) { InitializeFieldRVAs(); var rid = field.token.RID; RVA rva; if (!metadata.FieldRVAs.TryGetValue(rid, out rva)) return 0; var size = GetFieldTypeSize(field.FieldType); if (size == 0 || rva == 0) return 0; metadata.FieldRVAs.Remove(rid); field.InitialValue = GetFieldInitializeValue(size, rva); return (int)rva; } byte[] GetFieldInitializeValue(int size, RVA rva) { var section = image.GetSectionAtVirtualAddress(rva); if (section == null) return Empty.Array; var value = new byte[size]; Buffer.BlockCopy(section.Data, (int)(rva - section.VirtualAddress), value, 0, size); return value; } static int GetFieldTypeSize(TypeReference type) { int size = 0; switch (type.etype) { case ElementType.Boolean: case ElementType.U1: case ElementType.I1: size = 1; break; case ElementType.U2: case ElementType.I2: case ElementType.Char: size = 2; break; case ElementType.U4: case ElementType.I4: case ElementType.R4: size = 4; break; case ElementType.U8: case ElementType.I8: case ElementType.R8: size = 8; break; case ElementType.Ptr: case ElementType.FnPtr: size = IntPtr.Size; break; case ElementType.CModOpt: case ElementType.CModReqD: return GetFieldTypeSize(((IModifierType)type).ElementType); default: var field_type = Mixin.CheckedResolve(type); if (field_type.HasLayoutInfo) size = field_type.ClassSize; break; } return size; } void InitializeFieldRVAs() { if (metadata.FieldRVAs != null) return; int length = MoveTo(Table.FieldRVA); var field_rvas = metadata.FieldRVAs = new Dictionary(length); for (int i = 0; i < length; i++) { var rva = ReadUInt32(); var field = ReadTableIndex(Table.Field); field_rvas.Add(field, rva); } } public int ReadFieldLayout(FieldDefinition field) { InitializeFieldLayouts(); var rid = field.token.RID; uint offset; if (!metadata.FieldLayouts.TryGetValue(rid, out offset)) return Mixin.NoDataMarker; metadata.FieldLayouts.Remove(rid); return (int)offset; } void InitializeFieldLayouts() { if (metadata.FieldLayouts != null) return; int length = MoveTo(Table.FieldLayout); var field_layouts = metadata.FieldLayouts = new Dictionary(length); for (int i = 0; i < length; i++) { var offset = ReadUInt32(); var field = ReadTableIndex(Table.Field); field_layouts.Add(field, offset); } } public bool HasEvents(TypeDefinition type) { InitializeEvents(); Range range; if (!metadata.TryGetEventsRange(type, out range)) return false; return range.Length > 0; } public Collection ReadEvents(TypeDefinition type) { InitializeEvents(); Range range; if (!metadata.TryGetEventsRange(type, out range)) return new MemberDefinitionCollection(type); var events = new MemberDefinitionCollection(type, (int)range.Length); metadata.RemoveEventsRange(type); if (range.Length == 0) return events; this.context = type; if (!MoveTo(Table.EventPtr, range.Start)) { if (!MoveTo(Table.Event, range.Start)) return events; for (uint i = 0; i < range.Length; i++) ReadEvent(range.Start + i, events); } else ReadPointers(Table.EventPtr, Table.Event, range, events, ReadEvent); return events; } void ReadEvent(uint event_rid, Collection events) { var attributes = (EventAttributes)ReadUInt16(); var name = ReadString(); var event_type = GetTypeDefOrRef(ReadMetadataToken(CodedIndex.TypeDefOrRef)); var @event = new EventDefinition(name, attributes, event_type); @event.token = new MetadataToken(TokenType.Event, event_rid); if (IsDeleted(@event)) return; events.Add(@event); } void InitializeEvents() { if (metadata.Events != null) return; int length = MoveTo(Table.EventMap); metadata.Events = new Dictionary(length); for (uint i = 1; i <= length; i++) { var type_rid = ReadTableIndex(Table.TypeDef); Range events_range = ReadEventsRange(i); metadata.AddEventsRange(type_rid, events_range); } } Range ReadEventsRange(uint rid) { return ReadListRange(rid, Table.EventMap, Table.Event); } public bool HasProperties(TypeDefinition type) { InitializeProperties(); Range range; if (!metadata.TryGetPropertiesRange(type, out range)) return false; return range.Length > 0; } public Collection ReadProperties(TypeDefinition type) { InitializeProperties(); Range range; if (!metadata.TryGetPropertiesRange(type, out range)) return new MemberDefinitionCollection(type); metadata.RemovePropertiesRange(type); var properties = new MemberDefinitionCollection(type, (int)range.Length); if (range.Length == 0) return properties; this.context = type; if (!MoveTo(Table.PropertyPtr, range.Start)) { if (!MoveTo(Table.Property, range.Start)) return properties; for (uint i = 0; i < range.Length; i++) ReadProperty(range.Start + i, properties); } else ReadPointers(Table.PropertyPtr, Table.Property, range, properties, ReadProperty); return properties; } void ReadProperty(uint property_rid, Collection properties) { var attributes = (PropertyAttributes)ReadUInt16(); var name = ReadString(); var signature = ReadBlobIndex(); var reader = ReadSignature(signature); const byte property_signature = 0x8; var calling_convention = reader.ReadByte(); if ((calling_convention & property_signature) == 0) throw new NotSupportedException(); var has_this = (calling_convention & 0x20) != 0; reader.ReadCompressedUInt32(); // count var property = new PropertyDefinition(name, attributes, reader.ReadTypeSignature()); property.HasThis = has_this; property.token = new MetadataToken(TokenType.Property, property_rid); if (IsDeleted(property)) return; properties.Add(property); } void InitializeProperties() { if (metadata.Properties != null) return; int length = MoveTo(Table.PropertyMap); metadata.Properties = new Dictionary(length); for (uint i = 1; i <= length; i++) { var type_rid = ReadTableIndex(Table.TypeDef); var properties_range = ReadPropertiesRange(i); metadata.AddPropertiesRange(type_rid, properties_range); } } Range ReadPropertiesRange(uint rid) { return ReadListRange(rid, Table.PropertyMap, Table.Property); } MethodSemanticsAttributes ReadMethodSemantics(MethodDefinition method) { InitializeMethodSemantics(); Row row; if (!metadata.Semantics.TryGetValue(method.token.RID, out row)) return MethodSemanticsAttributes.None; var type = method.DeclaringType; switch (row.Col1) { case MethodSemanticsAttributes.AddOn: GetEvent(type, row.Col2).add_method = method; break; case MethodSemanticsAttributes.Fire: GetEvent(type, row.Col2).invoke_method = method; break; case MethodSemanticsAttributes.RemoveOn: GetEvent(type, row.Col2).remove_method = method; break; case MethodSemanticsAttributes.Getter: GetProperty(type, row.Col2).get_method = method; break; case MethodSemanticsAttributes.Setter: GetProperty(type, row.Col2).set_method = method; break; case MethodSemanticsAttributes.Other: switch (row.Col2.TokenType) { case TokenType.Event: { var @event = GetEvent(type, row.Col2); if (@event.other_methods == null) @event.other_methods = new Collection(); @event.other_methods.Add(method); break; } case TokenType.Property: { var property = GetProperty(type, row.Col2); if (property.other_methods == null) property.other_methods = new Collection(); property.other_methods.Add(method); break; } default: throw new NotSupportedException(); } break; default: throw new NotSupportedException(); } metadata.Semantics.Remove(method.token.RID); return row.Col1; } static EventDefinition GetEvent(TypeDefinition type, MetadataToken token) { if (token.TokenType != TokenType.Event) throw new ArgumentException(); return GetMember(type.Events, token); } static PropertyDefinition GetProperty(TypeDefinition type, MetadataToken token) { if (token.TokenType != TokenType.Property) throw new ArgumentException(); return GetMember(type.Properties, token); } static TMember GetMember(Collection members, MetadataToken token) where TMember : IMemberDefinition { for (int i = 0; i < members.Count; i++) { var member = members[i]; if (member.MetadataToken == token) return member; } throw new ArgumentException(); } void InitializeMethodSemantics() { if (metadata.Semantics != null) return; int length = MoveTo(Table.MethodSemantics); var semantics = metadata.Semantics = new Dictionary>(0); for (uint i = 0; i < length; i++) { var attributes = (MethodSemanticsAttributes)ReadUInt16(); var method_rid = ReadTableIndex(Table.Method); var association = ReadMetadataToken(CodedIndex.HasSemantics); semantics[method_rid] = new Row(attributes, association); } } public PropertyDefinition ReadMethods(PropertyDefinition property) { ReadAllSemantics(property.DeclaringType); return property; } public EventDefinition ReadMethods(EventDefinition @event) { ReadAllSemantics(@event.DeclaringType); return @event; } public MethodSemanticsAttributes ReadAllSemantics(MethodDefinition method) { ReadAllSemantics(method.DeclaringType); return method.SemanticsAttributes; } void ReadAllSemantics(TypeDefinition type) { var methods = type.Methods; for (int i = 0; i < methods.Count; i++) { var method = methods[i]; if (method.sem_attrs_ready) continue; method.sem_attrs = ReadMethodSemantics(method); method.sem_attrs_ready = true; } } Range ReadParametersRange(uint method_rid) { return ReadListRange(method_rid, Table.Method, Table.Param); } public Collection ReadMethods(TypeDefinition type) { var methods_range = type.methods_range; if (methods_range.Length == 0) return new MemberDefinitionCollection(type); var methods = new MemberDefinitionCollection(type, (int)methods_range.Length); if (!MoveTo(Table.MethodPtr, methods_range.Start)) { if (!MoveTo(Table.Method, methods_range.Start)) return methods; for (uint i = 0; i < methods_range.Length; i++) ReadMethod(methods_range.Start + i, methods); } else ReadPointers(Table.MethodPtr, Table.Method, methods_range, methods, ReadMethod); return methods; } void ReadPointers(Table ptr, Table table, Range range, Collection members, Action> reader) where TMember : IMemberDefinition { for (uint i = 0; i < range.Length; i++) { MoveTo(ptr, range.Start + i); var rid = ReadTableIndex(table); MoveTo(table, rid); reader(rid, members); } } static bool IsDeleted(IMemberDefinition member) { return member.IsSpecialName && member.Name == "_Deleted"; } void InitializeMethods() { if (metadata.Methods != null) return; metadata.Methods = new MethodDefinition[image.GetTableLength(Table.Method)]; } void ReadMethod(uint method_rid, Collection methods) { var method = new MethodDefinition(); method.rva = ReadUInt32(); method.ImplAttributes = (MethodImplAttributes)ReadUInt16(); method.Attributes = (MethodAttributes)ReadUInt16(); method.Name = ReadString(); method.token = new MetadataToken(TokenType.Method, method_rid); if (IsDeleted(method)) return; methods.Add(method); // attach method var signature = ReadBlobIndex(); var param_range = ReadParametersRange(method_rid); this.context = method; ReadMethodSignature(signature, method); metadata.AddMethodDefinition(method); if (param_range.Length == 0) return; var position = base.position; ReadParameters(method, param_range); base.position = position; } void ReadParameters(MethodDefinition method, Range param_range) { if (!MoveTo(Table.ParamPtr, param_range.Start)) { if (!MoveTo(Table.Param, param_range.Start)) return; for (uint i = 0; i < param_range.Length; i++) ReadParameter(param_range.Start + i, method); } else ReadParameterPointers(method, param_range); } void ReadParameterPointers(MethodDefinition method, Range range) { for (uint i = 0; i < range.Length; i++) { MoveTo(Table.ParamPtr, range.Start + i); var rid = ReadTableIndex(Table.Param); MoveTo(Table.Param, rid); ReadParameter(rid, method); } } void ReadParameter(uint param_rid, MethodDefinition method) { var attributes = (ParameterAttributes)ReadUInt16(); var sequence = ReadUInt16(); var name = ReadString(); var parameter = sequence == 0 ? method.MethodReturnType.Parameter : method.Parameters[sequence - 1]; parameter.token = new MetadataToken(TokenType.Param, param_rid); parameter.Name = name; parameter.Attributes = attributes; } void ReadMethodSignature(uint signature, IMethodSignature method) { var reader = ReadSignature(signature); reader.ReadMethodSignature(method); } public PInvokeInfo ReadPInvokeInfo(MethodDefinition method) { InitializePInvokes(); Row row; var rid = method.token.RID; if (!metadata.PInvokes.TryGetValue(rid, out row)) return null; metadata.PInvokes.Remove(rid); return new PInvokeInfo( row.Col1, image.StringHeap.Read(row.Col2), module.ModuleReferences[(int)row.Col3 - 1]); } void InitializePInvokes() { if (metadata.PInvokes != null) return; int length = MoveTo(Table.ImplMap); var pinvokes = metadata.PInvokes = new Dictionary>(length); for (int i = 1; i <= length; i++) { var attributes = (PInvokeAttributes)ReadUInt16(); var method = ReadMetadataToken(CodedIndex.MemberForwarded); var name = ReadStringIndex(); var scope = ReadTableIndex(Table.File); if (method.TokenType != TokenType.Method) continue; pinvokes.Add(method.RID, new Row(attributes, name, scope)); } } public bool HasGenericParameters(IGenericParameterProvider provider) { InitializeGenericParameters(); Range range; if (!metadata.TryGetGenericParameterRange(provider, out range)) return false; return range.Length > 0; } public Collection ReadGenericParameters(IGenericParameterProvider provider) { InitializeGenericParameters(); Range range; if (!metadata.TryGetGenericParameterRange(provider, out range) || !MoveTo(Table.GenericParam, range.Start)) return new GenericParameterCollection(provider); metadata.RemoveGenericParameterRange(provider); var generic_parameters = new GenericParameterCollection(provider, (int)range.Length); for (uint i = 0; i < range.Length; i++) { ReadUInt16(); // index var flags = (GenericParameterAttributes)ReadUInt16(); ReadMetadataToken(CodedIndex.TypeOrMethodDef); var name = ReadString(); var parameter = new GenericParameter(name, provider); parameter.token = new MetadataToken(TokenType.GenericParam, range.Start + i); parameter.Attributes = flags; generic_parameters.Add(parameter); } return generic_parameters; } void InitializeGenericParameters() { if (metadata.GenericParameters != null) return; metadata.GenericParameters = InitializeRanges( Table.GenericParam, () => { Advance(4); var next = ReadMetadataToken(CodedIndex.TypeOrMethodDef); ReadStringIndex(); return next; }); } Dictionary InitializeRanges(Table table, Func get_next) { int length = MoveTo(table); var ranges = new Dictionary(length); if (length == 0) return ranges; MetadataToken owner = MetadataToken.Zero; Range range = new Range(1, 0); for (uint i = 1; i <= length; i++) { var next = get_next(); if (i == 1) { owner = next; range.Length++; } else if (next != owner) { if (owner.RID != 0) ranges.Add(owner, range); range = new Range(i, 1); owner = next; } else range.Length++; } if (owner != MetadataToken.Zero && !ranges.ContainsKey(owner)) ranges.Add(owner, range); return ranges; } public bool HasGenericConstraints(GenericParameter generic_parameter) { InitializeGenericConstraints(); MetadataToken[] mapping; if (!metadata.TryGetGenericConstraintMapping(generic_parameter, out mapping)) return false; return mapping.Length > 0; } public Collection ReadGenericConstraints(GenericParameter generic_parameter) { InitializeGenericConstraints(); MetadataToken[] mapping; if (!metadata.TryGetGenericConstraintMapping(generic_parameter, out mapping)) return new Collection(); var constraints = new Collection(mapping.Length); this.context = (IGenericContext)generic_parameter.Owner; for (int i = 0; i < mapping.Length; i++) constraints.Add(GetTypeDefOrRef(mapping[i])); metadata.RemoveGenericConstraintMapping(generic_parameter); return constraints; } void InitializeGenericConstraints() { if (metadata.GenericConstraints != null) return; var length = MoveTo(Table.GenericParamConstraint); metadata.GenericConstraints = new Dictionary(length); for (int i = 1; i <= length; i++) AddGenericConstraintMapping( ReadTableIndex(Table.GenericParam), ReadMetadataToken(CodedIndex.TypeDefOrRef)); } void AddGenericConstraintMapping(uint generic_parameter, MetadataToken constraint) { metadata.SetGenericConstraintMapping( generic_parameter, AddMapping(metadata.GenericConstraints, generic_parameter, constraint)); } public bool HasOverrides(MethodDefinition method) { InitializeOverrides(); MetadataToken[] mapping; if (!metadata.TryGetOverrideMapping(method, out mapping)) return false; return mapping.Length > 0; } public Collection ReadOverrides(MethodDefinition method) { InitializeOverrides(); MetadataToken[] mapping; if (!metadata.TryGetOverrideMapping(method, out mapping)) return new Collection(); var overrides = new Collection(mapping.Length); this.context = method; for (int i = 0; i < mapping.Length; i++) overrides.Add((MethodReference)LookupToken(mapping[i])); metadata.RemoveOverrideMapping(method); return overrides; } void InitializeOverrides() { if (metadata.Overrides != null) return; var length = MoveTo(Table.MethodImpl); metadata.Overrides = new Dictionary(length); for (int i = 1; i <= length; i++) { ReadTableIndex(Table.TypeDef); var method = ReadMetadataToken(CodedIndex.MethodDefOrRef); if (method.TokenType != TokenType.Method) throw new NotSupportedException(); var @override = ReadMetadataToken(CodedIndex.MethodDefOrRef); AddOverrideMapping(method.RID, @override); } } void AddOverrideMapping(uint method_rid, MetadataToken @override) { metadata.SetOverrideMapping( method_rid, AddMapping(metadata.Overrides, method_rid, @override)); } public MethodBody ReadMethodBody(MethodDefinition method) { return code.ReadMethodBody(method); } public CallSite ReadCallSite(MetadataToken token) { if (!MoveTo(Table.StandAloneSig, token.RID)) return null; var signature = ReadBlobIndex(); var call_site = new CallSite(); ReadMethodSignature(signature, call_site); call_site.MetadataToken = token; return call_site; } public VariableDefinitionCollection ReadVariables(MetadataToken local_var_token) { if (!MoveTo(Table.StandAloneSig, local_var_token.RID)) return null; var reader = ReadSignature(ReadBlobIndex()); const byte local_sig = 0x7; if (reader.ReadByte() != local_sig) throw new NotSupportedException(); var count = reader.ReadCompressedUInt32(); if (count == 0) return null; var variables = new VariableDefinitionCollection((int)count); for (int i = 0; i < count; i++) variables.Add(new VariableDefinition(reader.ReadTypeSignature())); return variables; } public IMetadataTokenProvider LookupToken(MetadataToken token) { var rid = token.RID; if (rid == 0) return null; IMetadataTokenProvider element; var position = this.position; var context = this.context; switch (token.TokenType) { case TokenType.TypeDef: element = GetTypeDefinition(rid); break; case TokenType.TypeRef: element = GetTypeReference(rid); break; case TokenType.TypeSpec: element = GetTypeSpecification(rid); break; case TokenType.Field: element = GetFieldDefinition(rid); break; case TokenType.Method: element = GetMethodDefinition(rid); break; case TokenType.MemberRef: element = GetMemberReference(rid); break; case TokenType.MethodSpec: element = GetMethodSpecification(rid); break; default: return null; } this.position = position; this.context = context; return element; } public FieldDefinition GetFieldDefinition(uint rid) { InitializeTypeDefinitions(); var field = metadata.GetFieldDefinition(rid); if (field != null) return field; return LookupField(rid); } FieldDefinition LookupField(uint rid) { var type = metadata.GetFieldDeclaringType(rid); if (type == null) return null; InitializeCollection(type.Fields); return metadata.GetFieldDefinition(rid); } public MethodDefinition GetMethodDefinition(uint rid) { InitializeTypeDefinitions(); var method = metadata.GetMethodDefinition(rid); if (method != null) return method; return LookupMethod(rid); } MethodDefinition LookupMethod(uint rid) { var type = metadata.GetMethodDeclaringType(rid); if (type == null) return null; InitializeCollection(type.Methods); return metadata.GetMethodDefinition(rid); } MethodSpecification GetMethodSpecification(uint rid) { if (!MoveTo(Table.MethodSpec, rid)) return null; var element_method = (MethodReference)LookupToken( ReadMetadataToken(CodedIndex.MethodDefOrRef)); var signature = ReadBlobIndex(); var method_spec = ReadMethodSpecSignature(signature, element_method); method_spec.token = new MetadataToken(TokenType.MethodSpec, rid); return method_spec; } MethodSpecification ReadMethodSpecSignature(uint signature, MethodReference method) { var reader = ReadSignature(signature); const byte methodspec_sig = 0x0a; var call_conv = reader.ReadByte(); if (call_conv != methodspec_sig) throw new NotSupportedException(); var instance = new GenericInstanceMethod(method); reader.ReadGenericInstanceSignature(method, instance); return instance; } MemberReference GetMemberReference(uint rid) { InitializeMemberReferences(); var member = metadata.GetMemberReference(rid); if (member != null) return member; member = ReadMemberReference(rid); if (member != null && !member.ContainsGenericParameter) metadata.AddMemberReference(member); return member; } MemberReference ReadMemberReference(uint rid) { if (!MoveTo(Table.MemberRef, rid)) return null; var token = ReadMetadataToken(CodedIndex.MemberRefParent); var name = ReadString(); var signature = ReadBlobIndex(); MemberReference member; switch (token.TokenType) { case TokenType.TypeDef: case TokenType.TypeRef: case TokenType.TypeSpec: member = ReadTypeMemberReference(token, name, signature); break; case TokenType.Method: member = ReadMethodMemberReference(token, name, signature); break; default: throw new NotSupportedException(); } member.token = new MetadataToken(TokenType.MemberRef, rid); return member; } MemberReference ReadTypeMemberReference(MetadataToken type, string name, uint signature) { var declaring_type = GetTypeDefOrRef(type); if (!declaring_type.IsArray) this.context = declaring_type; var member = ReadMemberReferenceSignature(signature, declaring_type); member.Name = name; return member; } MemberReference ReadMemberReferenceSignature(uint signature, TypeReference declaring_type) { var reader = ReadSignature(signature); const byte field_sig = 0x6; if (reader.buffer[reader.position] == field_sig) { reader.position++; var field = new FieldReference(); field.DeclaringType = declaring_type; field.FieldType = reader.ReadTypeSignature(); return field; } else { var method = new MethodReference(); method.DeclaringType = declaring_type; reader.ReadMethodSignature(method); return method; } } MemberReference ReadMethodMemberReference(MetadataToken token, string name, uint signature) { var method = GetMethodDefinition(token.RID); this.context = method; var member = ReadMemberReferenceSignature(signature, method.DeclaringType); member.Name = name; return member; } void InitializeMemberReferences() { if (metadata.MemberReferences != null) return; metadata.MemberReferences = new MemberReference[image.GetTableLength(Table.MemberRef)]; } public IEnumerable GetMemberReferences() { InitializeMemberReferences(); var length = image.GetTableLength(Table.MemberRef); var type_system = module.TypeSystem; var context = new MethodReference(string.Empty, type_system.Void); context.DeclaringType = new TypeReference(string.Empty, string.Empty, module, type_system.Corlib); var member_references = new MemberReference[length]; for (uint i = 1; i <= length; i++) { this.context = context; member_references[i - 1] = GetMemberReference(i); } return member_references; } void InitializeConstants() { if (metadata.Constants != null) return; var length = MoveTo(Table.Constant); var constants = metadata.Constants = new Dictionary>(length); for (uint i = 1; i <= length; i++) { var type = (ElementType)ReadUInt16(); var owner = ReadMetadataToken(CodedIndex.HasConstant); var signature = ReadBlobIndex(); constants.Add(owner, new Row(type, signature)); } } public object ReadConstant(IConstantProvider owner) { InitializeConstants(); Row row; if (!metadata.Constants.TryGetValue(owner.MetadataToken, out row)) return Mixin.NoValue; metadata.Constants.Remove(owner.MetadataToken); switch (row.Col1) { case ElementType.Class: case ElementType.Object: return null; case ElementType.String: return ReadConstantString(ReadBlob(row.Col2)); default: return ReadConstantPrimitive(row.Col1, row.Col2); } } static string ReadConstantString(byte[] blob) { var length = blob.Length; if ((length & 1) == 1) length--; return Encoding.Unicode.GetString(blob, 0, length); } object ReadConstantPrimitive(ElementType type, uint signature) { var reader = ReadSignature(signature); return reader.ReadConstantSignature(type); } void InitializeCustomAttributes() { if (metadata.CustomAttributes != null) return; metadata.CustomAttributes = InitializeRanges( Table.CustomAttribute, () => { var next = ReadMetadataToken(CodedIndex.HasCustomAttribute); ReadMetadataToken(CodedIndex.CustomAttributeType); ReadBlobIndex(); return next; }); } public bool HasCustomAttributes(ICustomAttributeProvider owner) { InitializeCustomAttributes(); Range range; if (!metadata.TryGetCustomAttributeRange(owner, out range)) return false; return range.Length > 0; } public Collection ReadCustomAttributes(ICustomAttributeProvider owner) { InitializeCustomAttributes(); Range range; if (!metadata.TryGetCustomAttributeRange(owner, out range) || !MoveTo(Table.CustomAttribute, range.Start)) return new Collection(); var custom_attributes = new Collection((int)range.Length); for (int i = 0; i < range.Length; i++) { ReadMetadataToken(CodedIndex.HasCustomAttribute); var constructor = (MethodReference)LookupToken( ReadMetadataToken(CodedIndex.CustomAttributeType)); var signature = ReadBlobIndex(); custom_attributes.Add(new CustomAttribute(signature, constructor)); } metadata.RemoveCustomAttributeRange(owner); return custom_attributes; } public byte[] ReadCustomAttributeBlob(uint signature) { return ReadBlob(signature); } public void ReadCustomAttributeSignature(CustomAttribute attribute) { var reader = ReadSignature(attribute.signature); if (!reader.CanReadMore()) return; if (reader.ReadUInt16() != 0x0001) throw new InvalidOperationException(); var constructor = attribute.Constructor; if (constructor.HasParameters) reader.ReadCustomAttributeConstructorArguments(attribute, constructor.Parameters); if (!reader.CanReadMore()) return; var named = reader.ReadUInt16(); if (named == 0) return; reader.ReadCustomAttributeNamedArguments(named, ref attribute.fields, ref attribute.properties); } void InitializeMarshalInfos() { if (metadata.FieldMarshals != null) return; var length = MoveTo(Table.FieldMarshal); var marshals = metadata.FieldMarshals = new Dictionary(length); for (int i = 0; i < length; i++) { var token = ReadMetadataToken(CodedIndex.HasFieldMarshal); var signature = ReadBlobIndex(); if (token.RID == 0) continue; marshals.Add(token, signature); } } public bool HasMarshalInfo(IMarshalInfoProvider owner) { InitializeMarshalInfos(); return metadata.FieldMarshals.ContainsKey(owner.MetadataToken); } public MarshalInfo ReadMarshalInfo(IMarshalInfoProvider owner) { InitializeMarshalInfos(); uint signature; if (!metadata.FieldMarshals.TryGetValue(owner.MetadataToken, out signature)) return null; var reader = ReadSignature(signature); metadata.FieldMarshals.Remove(owner.MetadataToken); return reader.ReadMarshalInfo(); } void InitializeSecurityDeclarations() { if (metadata.SecurityDeclarations != null) return; metadata.SecurityDeclarations = InitializeRanges( Table.DeclSecurity, () => { ReadUInt16(); var next = ReadMetadataToken(CodedIndex.HasDeclSecurity); ReadBlobIndex(); return next; }); } public bool HasSecurityDeclarations(ISecurityDeclarationProvider owner) { InitializeSecurityDeclarations(); Range range; if (!metadata.TryGetSecurityDeclarationRange(owner, out range)) return false; return range.Length > 0; } public Collection ReadSecurityDeclarations(ISecurityDeclarationProvider owner) { InitializeSecurityDeclarations(); Range range; if (!metadata.TryGetSecurityDeclarationRange(owner, out range) || !MoveTo(Table.DeclSecurity, range.Start)) return new Collection(); var security_declarations = new Collection((int)range.Length); for (int i = 0; i < range.Length; i++) { var action = (SecurityAction)ReadUInt16(); ReadMetadataToken(CodedIndex.HasDeclSecurity); var signature = ReadBlobIndex(); security_declarations.Add(new SecurityDeclaration(action, signature, module)); } metadata.RemoveSecurityDeclarationRange(owner); return security_declarations; } public byte[] ReadSecurityDeclarationBlob(uint signature) { return ReadBlob(signature); } public void ReadSecurityDeclarationSignature(SecurityDeclaration declaration) { var signature = declaration.signature; var reader = ReadSignature(signature); if (reader.buffer[reader.position] != '.') { ReadXmlSecurityDeclaration(signature, declaration); return; } reader.position++; var count = reader.ReadCompressedUInt32(); var attributes = new Collection((int)count); for (int i = 0; i < count; i++) attributes.Add(reader.ReadSecurityAttribute()); declaration.security_attributes = attributes; } void ReadXmlSecurityDeclaration(uint signature, SecurityDeclaration declaration) { var blob = ReadBlob(signature); var attributes = new Collection(1); var attribute = new SecurityAttribute( module.TypeSystem.LookupType("System.Security.Permissions", "PermissionSetAttribute")); attribute.properties = new Collection(1); attribute.properties.Add( new CustomAttributeNamedArgument( "XML", new CustomAttributeArgument( module.TypeSystem.String, Encoding.Unicode.GetString(blob, 0, blob.Length)))); attributes.Add(attribute); declaration.security_attributes = attributes; } public Collection ReadExportedTypes() { var length = MoveTo(Table.ExportedType); if (length == 0) return new Collection(); var exported_types = new Collection(length); for (int i = 1; i <= length; i++) { var attributes = (TypeAttributes)ReadUInt32(); var identifier = ReadUInt32(); var name = ReadString(); var @namespace = ReadString(); var implementation = ReadMetadataToken(CodedIndex.Implementation); ExportedType declaring_type = null; IMetadataScope scope = null; switch (implementation.TokenType) { case TokenType.AssemblyRef: case TokenType.File: scope = GetExportedTypeScope(implementation); break; case TokenType.ExportedType: // FIXME: if the table is not properly sorted declaring_type = exported_types[(int)implementation.RID - 1]; break; } var exported_type = new ExportedType(@namespace, name, module, scope) { Attributes = attributes, Identifier = (int)identifier, DeclaringType = declaring_type, }; exported_type.token = new MetadataToken(TokenType.ExportedType, i); exported_types.Add(exported_type); } return exported_types; } IMetadataScope GetExportedTypeScope(MetadataToken token) { var position = this.position; IMetadataScope scope; switch (token.TokenType) { case TokenType.AssemblyRef: InitializeAssemblyReferences(); scope = metadata.AssemblyReferences[(int)token.RID - 1]; break; case TokenType.File: InitializeModuleReferences(); scope = GetModuleReferenceFromFile(token); break; default: throw new NotSupportedException(); } this.position = position; return scope; } ModuleReference GetModuleReferenceFromFile(MetadataToken token) { if (!MoveTo(Table.File, token.RID)) return null; ReadUInt32(); var file_name = ReadString(); var modules = module.ModuleReferences; ModuleReference reference; for (int i = 0; i < modules.Count; i++) { reference = modules[i]; if (reference.Name == file_name) return reference; } reference = new ModuleReference(file_name); modules.Add(reference); return reference; } static void InitializeCollection(object o) { } } sealed class SignatureReader : ByteBuffer { readonly MetadataReader reader; readonly uint start, sig_length; TypeSystem TypeSystem { get { return reader.module.TypeSystem; } } public SignatureReader(uint blob, MetadataReader reader) : base(reader.buffer) { this.reader = reader; MoveToBlob(blob); this.sig_length = ReadCompressedUInt32(); this.start = (uint)position; } void MoveToBlob(uint blob) { position = (int)(reader.image.BlobHeap.Offset + blob); } MetadataToken ReadTypeTokenSignature() { return Mixin.GetMetadataToken(CodedIndex.TypeDefOrRef, ReadCompressedUInt32()); } GenericParameter GetGenericParameter(GenericParameterType type, uint var) { var context = reader.context; int index = (int)var; if (context == null) return GetUnboundGenericParameter(type, index); IGenericParameterProvider provider; switch (type) { case GenericParameterType.Type: provider = context.Type; break; case GenericParameterType.Method: provider = context.Method; break; default: throw new NotSupportedException(); } if (!context.IsDefinition) CheckGenericContext(provider, index); if (index >= provider.GenericParameters.Count) return GetUnboundGenericParameter(type, index); return provider.GenericParameters[index]; } GenericParameter GetUnboundGenericParameter(GenericParameterType type, int index) { return new GenericParameter(index, type, reader.module); } static void CheckGenericContext(IGenericParameterProvider owner, int index) { var owner_parameters = owner.GenericParameters; for (int i = owner_parameters.Count; i <= index; i++) owner_parameters.Add(new GenericParameter(owner)); } public void ReadGenericInstanceSignature(IGenericParameterProvider provider, IGenericInstance instance) { var arity = ReadCompressedUInt32(); if (!provider.IsDefinition) CheckGenericContext(provider, (int)arity - 1); var instance_arguments = instance.GenericArguments; for (int i = 0; i < arity; i++) instance_arguments.Add(ReadTypeSignature()); } ArrayType ReadArrayTypeSignature() { var array = new ArrayType(ReadTypeSignature()); var rank = ReadCompressedUInt32(); var sizes = new uint[ReadCompressedUInt32()]; for (int i = 0; i < sizes.Length; i++) sizes[i] = ReadCompressedUInt32(); var low_bounds = new int[ReadCompressedUInt32()]; for (int i = 0; i < low_bounds.Length; i++) low_bounds[i] = ReadCompressedInt32(); array.Dimensions.Clear(); for (int i = 0; i < rank; i++) { int? lower = null, upper = null; if (i < low_bounds.Length) lower = low_bounds[i]; if (i < sizes.Length) upper = lower + (int)sizes[i] - 1; array.Dimensions.Add(new ArrayDimension(lower, upper)); } return array; } TypeReference GetTypeDefOrRef(MetadataToken token) { return reader.GetTypeDefOrRef(token); } public TypeReference ReadTypeSignature() { return ReadTypeSignature((ElementType)ReadByte()); } TypeReference ReadTypeSignature(ElementType etype) { switch (etype) { case ElementType.ValueType: { var value_type = GetTypeDefOrRef(ReadTypeTokenSignature()); value_type.IsValueType = true; return value_type; } case ElementType.Class: return GetTypeDefOrRef(ReadTypeTokenSignature()); case ElementType.Ptr: return new PointerType(ReadTypeSignature()); case ElementType.FnPtr: { var fptr = new FunctionPointerType(); ReadMethodSignature(fptr); return fptr; } case ElementType.ByRef: return new ByReferenceType(ReadTypeSignature()); case ElementType.Pinned: return new PinnedType(ReadTypeSignature()); case ElementType.SzArray: return new ArrayType(ReadTypeSignature()); case ElementType.Array: return ReadArrayTypeSignature(); case ElementType.CModOpt: return new OptionalModifierType( GetTypeDefOrRef(ReadTypeTokenSignature()), ReadTypeSignature()); case ElementType.CModReqD: return new RequiredModifierType( GetTypeDefOrRef(ReadTypeTokenSignature()), ReadTypeSignature()); case ElementType.Sentinel: return new SentinelType(ReadTypeSignature()); case ElementType.Var: return GetGenericParameter(GenericParameterType.Type, ReadCompressedUInt32()); case ElementType.MVar: return GetGenericParameter(GenericParameterType.Method, ReadCompressedUInt32()); case ElementType.GenericInst: { var is_value_type = ReadByte() == (byte)ElementType.ValueType; var element_type = GetTypeDefOrRef(ReadTypeTokenSignature()); var generic_instance = new GenericInstanceType(element_type); ReadGenericInstanceSignature(element_type, generic_instance); if (is_value_type) { generic_instance.IsValueType = true; element_type.GetElementType().IsValueType = true; } return generic_instance; } case ElementType.Object: return TypeSystem.Object; case ElementType.Void: return TypeSystem.Void; case ElementType.TypedByRef: return TypeSystem.TypedReference; case ElementType.I: return TypeSystem.IntPtr; case ElementType.U: return TypeSystem.UIntPtr; default: return GetPrimitiveType(etype); } } public void ReadMethodSignature(IMethodSignature method) { var calling_convention = ReadByte(); const byte has_this = 0x20; const byte explicit_this = 0x40; if ((calling_convention & has_this) != 0) { method.HasThis = true; calling_convention = (byte)(calling_convention & ~has_this); } if ((calling_convention & explicit_this) != 0) { method.ExplicitThis = true; calling_convention = (byte)(calling_convention & ~explicit_this); } method.CallingConvention = (MethodCallingConvention)calling_convention; var generic_context = method as MethodReference; if (generic_context != null && !generic_context.DeclaringType.IsArray) reader.context = generic_context; if ((calling_convention & 0x10) != 0) { var arity = ReadCompressedUInt32(); if (generic_context != null && !generic_context.IsDefinition) CheckGenericContext(generic_context, (int)arity - 1); } var param_count = ReadCompressedUInt32(); method.MethodReturnType.ReturnType = ReadTypeSignature(); if (param_count == 0) return; Collection parameters; var method_ref = method as MethodReference; if (method_ref != null) parameters = method_ref.parameters = new ParameterDefinitionCollection(method, (int)param_count); else parameters = method.Parameters; for (int i = 0; i < param_count; i++) parameters.Add(new ParameterDefinition(ReadTypeSignature())); } public object ReadConstantSignature(ElementType type) { return ReadPrimitiveValue(type); } public void ReadCustomAttributeConstructorArguments(CustomAttribute attribute, Collection parameters) { var count = parameters.Count; if (count == 0) return; attribute.arguments = new Collection(count); for (int i = 0; i < count; i++) attribute.arguments.Add( ReadCustomAttributeFixedArgument(parameters[i].ParameterType)); } CustomAttributeArgument ReadCustomAttributeFixedArgument(TypeReference type) { if (type.IsArray) return ReadCustomAttributeFixedArrayArgument((ArrayType)type); return ReadCustomAttributeElement(type); } public void ReadCustomAttributeNamedArguments(ushort count, ref Collection fields, ref Collection properties) { for (int i = 0; i < count; i++) ReadCustomAttributeNamedArgument(ref fields, ref properties); } void ReadCustomAttributeNamedArgument(ref Collection fields, ref Collection properties) { var kind = ReadByte(); var type = ReadCustomAttributeFieldOrPropType(); var name = ReadUTF8String(); Collection container; switch (kind) { case 0x53: container = GetCustomAttributeNamedArgumentCollection(ref fields); break; case 0x54: container = GetCustomAttributeNamedArgumentCollection(ref properties); break; default: throw new NotSupportedException(); } container.Add(new CustomAttributeNamedArgument(name, ReadCustomAttributeFixedArgument(type))); } static Collection GetCustomAttributeNamedArgumentCollection(ref Collection collection) { if (collection != null) return collection; return collection = new Collection(); } CustomAttributeArgument ReadCustomAttributeFixedArrayArgument(ArrayType type) { var length = ReadUInt32(); if (length == 0xffffffff) return new CustomAttributeArgument(type, null); if (length == 0) return new CustomAttributeArgument(type, Empty.Array); var arguments = new CustomAttributeArgument[length]; var element_type = type.ElementType; for (int i = 0; i < length; i++) arguments[i] = ReadCustomAttributeElement(element_type); return new CustomAttributeArgument(type, arguments); } CustomAttributeArgument ReadCustomAttributeElement(TypeReference type) { if (type.IsArray) return ReadCustomAttributeFixedArrayArgument((ArrayType)type); return new CustomAttributeArgument( type, type.etype == ElementType.Object ? ReadCustomAttributeElement(ReadCustomAttributeFieldOrPropType()) : ReadCustomAttributeElementValue(type)); } object ReadCustomAttributeElementValue(TypeReference type) { var etype = type.etype; switch (etype) { case ElementType.String: return ReadUTF8String(); case ElementType.None: if (Mixin.IsTypeOf(type,"System", "Type")) return ReadTypeReference(); return ReadCustomAttributeEnum(type); default: return ReadPrimitiveValue(etype); } } object ReadPrimitiveValue(ElementType type) { switch (type) { case ElementType.Boolean: return ReadByte() == 1; case ElementType.I1: return (sbyte)ReadByte(); case ElementType.U1: return ReadByte(); case ElementType.Char: return (char)ReadUInt16(); case ElementType.I2: return ReadInt16(); case ElementType.U2: return ReadUInt16(); case ElementType.I4: return ReadInt32(); case ElementType.U4: return ReadUInt32(); case ElementType.I8: return ReadInt64(); case ElementType.U8: return ReadUInt64(); case ElementType.R4: return ReadSingle(); case ElementType.R8: return ReadDouble(); default: throw new NotImplementedException(type.ToString()); } } TypeReference GetPrimitiveType(ElementType etype) { switch (etype) { case ElementType.Boolean: return TypeSystem.Boolean; case ElementType.Char: return TypeSystem.Char; case ElementType.I1: return TypeSystem.SByte; case ElementType.U1: return TypeSystem.Byte; case ElementType.I2: return TypeSystem.Int16; case ElementType.U2: return TypeSystem.UInt16; case ElementType.I4: return TypeSystem.Int32; case ElementType.U4: return TypeSystem.UInt32; case ElementType.I8: return TypeSystem.Int64; case ElementType.U8: return TypeSystem.UInt64; case ElementType.R4: return TypeSystem.Single; case ElementType.R8: return TypeSystem.Double; case ElementType.String: return TypeSystem.String; default: throw new NotImplementedException(etype.ToString()); } } TypeReference ReadCustomAttributeFieldOrPropType() { var etype = (ElementType)ReadByte(); switch (etype) { case ElementType.Boxed: return TypeSystem.Object; case ElementType.SzArray: return new ArrayType(ReadCustomAttributeFieldOrPropType()); case ElementType.Enum: return ReadTypeReference(); case ElementType.Type: return TypeSystem.LookupType("System", "Type"); default: return GetPrimitiveType(etype); } } public TypeReference ReadTypeReference() { return TypeParser.ParseType(reader.module, ReadUTF8String()); } object ReadCustomAttributeEnum(TypeReference enum_type) { try { TypeDefinition type = null; type = Mixin.CheckedResolve(enum_type); if (!type.IsEnum) throw new ArgumentException(); return ReadCustomAttributeElementValue(Mixin.GetEnumUnderlyingType(type)); } catch { //Resolve failed string name = enum_type.FullName + ", " + enum_type.scope.Name; Type type = Type.GetType(name); if (type == null || !type.IsEnum) return new ArgumentException(); var fields = type.GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public); Type eType = null; foreach(var i in fields) { eType = i.FieldType; break; } object val; if(eType == typeof(int)) { val = ReadPrimitiveValue(ElementType.I4); } else if (eType == typeof(long)) { val = ReadPrimitiveValue(ElementType.I8); } else if (eType == typeof(short)) { val = ReadPrimitiveValue(ElementType.I2); } else if (eType == typeof(byte)) { val = ReadPrimitiveValue(ElementType.U1); } else if (eType == typeof(uint)) { val = ReadPrimitiveValue(ElementType.U4); } else if (eType == typeof(ulong)) { val = ReadPrimitiveValue(ElementType.U8); } else if (eType == typeof(ushort)) { val = ReadPrimitiveValue(ElementType.U2); } else { val = ReadPrimitiveValue(ElementType.Void); } return Enum.ToObject(type, val); } } public SecurityAttribute ReadSecurityAttribute() { var attribute = new SecurityAttribute(ReadTypeReference()); ReadCompressedUInt32(); ReadCustomAttributeNamedArguments( (ushort)ReadCompressedUInt32(), ref attribute.fields, ref attribute.properties); return attribute; } public MarshalInfo ReadMarshalInfo() { var native = ReadNativeType(); switch (native) { case NativeType.Array: { var array = new ArrayMarshalInfo(); if (CanReadMore()) array.element_type = ReadNativeType(); if (CanReadMore()) array.size_parameter_index = (int)ReadCompressedUInt32(); if (CanReadMore()) array.size = (int)ReadCompressedUInt32(); if (CanReadMore()) array.size_parameter_multiplier = (int)ReadCompressedUInt32(); return array; } case NativeType.SafeArray: { var array = new SafeArrayMarshalInfo(); if (CanReadMore()) array.element_type = ReadVariantType(); return array; } case NativeType.FixedArray: { var array = new FixedArrayMarshalInfo(); if (CanReadMore()) array.size = (int)ReadCompressedUInt32(); if (CanReadMore()) array.element_type = ReadNativeType(); return array; } case NativeType.FixedSysString: { var sys_string = new FixedSysStringMarshalInfo(); if (CanReadMore()) sys_string.size = (int)ReadCompressedUInt32(); return sys_string; } case NativeType.CustomMarshaler: { var marshaler = new CustomMarshalInfo(); var guid_value = ReadUTF8String(); marshaler.guid = !string.IsNullOrEmpty(guid_value) ? new Guid(guid_value) : Guid.Empty; marshaler.unmanaged_type = ReadUTF8String(); marshaler.managed_type = ReadTypeReference(); marshaler.cookie = ReadUTF8String(); return marshaler; } default: return new MarshalInfo(native); } } NativeType ReadNativeType() { return (NativeType)ReadByte(); } VariantType ReadVariantType() { return (VariantType)ReadByte(); } string ReadUTF8String() { if (buffer[position] == 0xff) { position++; return null; } var length = (int)ReadCompressedUInt32(); if (length == 0) return string.Empty; var @string = Encoding.UTF8.GetString(buffer, position, buffer[position + length - 1] == 0 ? length - 1 : length); position += length; return @string; } public bool CanReadMore() { return position - start < sig_length; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/AssemblyWriter.cs ================================================ // // AssemblyWriter.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using System.IO; using System.Text; using Mono.Collections.Generic; using Mono.Cecil.Cil; using Mono.Cecil.Metadata; using Mono.Cecil.PE; using RVA = System.UInt32; using RID = System.UInt32; using CodedRID = System.UInt32; using StringIndex = System.UInt32; using BlobIndex = System.UInt32; namespace Mono.Cecil { } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/BaseAssemblyResolver.cs ================================================ // // BaseAssemblyResolver.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using System.IO; using System.Text; using Mono.Collections.Generic; namespace Mono.Cecil { public delegate AssemblyDefinition AssemblyResolveEventHandler (object sender, AssemblyNameReference reference); public sealed class AssemblyResolveEventArgs : EventArgs { readonly AssemblyNameReference reference; public AssemblyNameReference AssemblyReference { get { return reference; } } public AssemblyResolveEventArgs (AssemblyNameReference reference) { this.reference = reference; } } public class AssemblyResolutionException : FileNotFoundException { readonly AssemblyNameReference reference; public AssemblyNameReference AssemblyReference { get { return reference; } } public AssemblyResolutionException (AssemblyNameReference reference) : base (string.Format ("Failed to resolve assembly: '{0}'", reference)) { this.reference = reference; } } public abstract class BaseAssemblyResolver : IAssemblyResolver { static readonly bool on_mono = Type.GetType ("Mono.Runtime") != null; readonly Collection directories; public void AddSearchDirectory (string directory) { directories.Add (directory); } public void RemoveSearchDirectory (string directory) { directories.Remove (directory); } public string [] GetSearchDirectories () { var directories = new string [this.directories.size]; Array.Copy (this.directories.items, directories, directories.Length); return directories; } public virtual AssemblyDefinition Resolve (string fullName) { return Resolve (fullName, new ReaderParameters ()); } public virtual AssemblyDefinition Resolve (string fullName, ReaderParameters parameters) { if (fullName == null) throw new ArgumentNullException ("fullName"); return Resolve (AssemblyNameReference.Parse (fullName), parameters); } public event AssemblyResolveEventHandler ResolveFailure; protected BaseAssemblyResolver () { directories = new Collection (2) { ".", "bin" }; } AssemblyDefinition GetAssembly (string file, ReaderParameters parameters) { if (parameters.AssemblyResolver == null) parameters.AssemblyResolver = this; return ModuleDefinition.ReadModule (file, parameters).Assembly; } public virtual AssemblyDefinition Resolve (AssemblyNameReference name) { return Resolve (name, new ReaderParameters ()); } public virtual AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters) { if (name == null) throw new ArgumentNullException ("name"); if (parameters == null) parameters = new ReaderParameters (); var assembly = SearchDirectory (name, directories, parameters); if (assembly != null) return assembly; if (ResolveFailure != null) { assembly = ResolveFailure (this, name); if (assembly != null) return assembly; } throw new AssemblyResolutionException (name); } AssemblyDefinition SearchDirectory (AssemblyNameReference name, IEnumerable directories, ReaderParameters parameters) { var extensions = new [] { ".exe", ".dll" }; foreach (var directory in directories) { foreach (var extension in extensions) { string file = Path.Combine (directory, name.Name + extension); if (File.Exists (file)) return GetAssembly (file, parameters); } } return null; } static bool IsZero (Version version) { return version == null || (version.Major == 0 && version.Minor == 0 && version.Build == 0 && version.Revision == 0); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/CallSite.cs ================================================ // // CallSite.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Text; using Mono.Collections.Generic; namespace Mono.Cecil { public sealed class CallSite : IMethodSignature { readonly MethodReference signature; public bool HasThis { get { return signature.HasThis; } set { signature.HasThis = value; } } public bool ExplicitThis { get { return signature.ExplicitThis; } set { signature.ExplicitThis = value; } } public MethodCallingConvention CallingConvention { get { return signature.CallingConvention; } set { signature.CallingConvention = value; } } public bool HasParameters { get { return signature.HasParameters; } } public Collection Parameters { get { return signature.Parameters; } } public TypeReference ReturnType { get { return signature.MethodReturnType.ReturnType; } set { signature.MethodReturnType.ReturnType = value; } } public MethodReturnType MethodReturnType { get { return signature.MethodReturnType; } } public string Name { get { return string.Empty; } set { throw new InvalidOperationException (); } } public string Namespace { get { return string.Empty; } set { throw new InvalidOperationException (); } } public ModuleDefinition Module { get { return ReturnType.Module; } } public IMetadataScope Scope { get { return signature.ReturnType.Scope; } } public MetadataToken MetadataToken { get { return signature.token; } set { signature.token = value; } } public string FullName { get { var signature = new StringBuilder (); signature.Append (ReturnType.FullName); Mixin.MethodSignatureFullName (this,signature); return signature.ToString (); } } internal CallSite () { this.signature = new MethodReference (); this.signature.token = new MetadataToken (TokenType.Signature, 0); } public CallSite (TypeReference returnType) : this () { if (returnType == null) throw new ArgumentNullException ("returnType"); this.signature.ReturnType = returnType; } public override string ToString () { return FullName; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/CustomAttribute.cs ================================================ // // CustomAttribute.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Collections.Generic; namespace Mono.Cecil { public struct CustomAttributeArgument { readonly TypeReference type; readonly object value; public TypeReference Type { get { return type; } } public object Value { get { return value; } } public CustomAttributeArgument (TypeReference type, object value) { Mixin.CheckType (type); this.type = type; this.value = value; } } public struct CustomAttributeNamedArgument { readonly string name; readonly CustomAttributeArgument argument; public string Name { get { return name; } } public CustomAttributeArgument Argument { get { return argument; } } public CustomAttributeNamedArgument (string name, CustomAttributeArgument argument) { Mixin.CheckName (name); this.name = name; this.argument = argument; } } public interface ICustomAttribute { TypeReference AttributeType { get; } bool HasFields { get; } bool HasProperties { get; } Collection Fields { get; } Collection Properties { get; } } public sealed class CustomAttribute : ICustomAttribute { readonly internal uint signature; internal bool resolved; MethodReference constructor; byte [] blob; internal Collection arguments; internal Collection fields; internal Collection properties; public MethodReference Constructor { get { return constructor; } set { constructor = value; } } public TypeReference AttributeType { get { return constructor.DeclaringType; } } public bool IsResolved { get { return resolved; } } public bool HasConstructorArguments { get { Resolve (); return !Mixin.IsNullOrEmpty (arguments); } } public Collection ConstructorArguments { get { Resolve (); return arguments ?? (arguments = new Collection ()); } } public bool HasFields { get { Resolve (); return !Mixin.IsNullOrEmpty (fields); } } public Collection Fields { get { Resolve (); return fields ?? (fields = new Collection ()); } } public bool HasProperties { get { Resolve (); return !Mixin.IsNullOrEmpty (properties); } } public Collection Properties { get { Resolve (); return properties ?? (properties = new Collection ()); } } internal bool HasImage { get { return constructor != null && constructor.HasImage; } } internal ModuleDefinition Module { get { return constructor.Module; } } internal CustomAttribute (uint signature, MethodReference constructor) { this.signature = signature; this.constructor = constructor; this.resolved = false; } public CustomAttribute (MethodReference constructor) { this.constructor = constructor; this.resolved = true; } public CustomAttribute (MethodReference constructor, byte [] blob) { this.constructor = constructor; this.resolved = false; this.blob = blob; } public byte [] GetBlob () { if (blob != null) return blob; if (!HasImage) throw new NotSupportedException (); return Module.Read (ref blob, this, (attribute, reader) => reader.ReadCustomAttributeBlob (attribute.signature)); } void Resolve () { if (resolved || !HasImage) return; Module.Read (this, (attribute, reader) => { try { reader.ReadCustomAttributeSignature (attribute); resolved = true; } catch (ResolutionException) { if (arguments != null) arguments.Clear (); if (fields != null) fields.Clear (); if (properties != null) properties.Clear (); resolved = false; } return this; }); } } static partial class Mixin { public static void CheckName (string name) { if (name == null) throw new ArgumentNullException ("name"); if (name.Length == 0) throw new ArgumentException ("Empty name"); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/DefaultAssemblyResolver.cs ================================================ // // DefaultAssemblyResolver.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; namespace Mono.Cecil { public class DefaultAssemblyResolver : BaseAssemblyResolver { readonly IDictionary cache; public DefaultAssemblyResolver () { cache = new Dictionary (StringComparer.Ordinal); } public override AssemblyDefinition Resolve (AssemblyNameReference name) { if (name == null) throw new ArgumentNullException ("name"); AssemblyDefinition assembly; if (cache.TryGetValue (name.FullName, out assembly)) return assembly; assembly = base.Resolve (name); cache [name.FullName] = assembly; return assembly; } protected void RegisterAssembly (AssemblyDefinition assembly) { if (assembly == null) throw new ArgumentNullException ("assembly"); var name = assembly.Name.FullName; if (cache.ContainsKey (name)) return; cache [name] = assembly; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/EmbeddedResource.cs ================================================ // // EmbeddedResource.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.IO; namespace Mono.Cecil { public sealed class EmbeddedResource : Resource { readonly MetadataReader reader; uint? offset; byte [] data; Stream stream; public override ResourceType ResourceType { get { return ResourceType.Embedded; } } public EmbeddedResource (string name, ManifestResourceAttributes attributes, byte [] data) : base (name, attributes) { this.data = data; } public EmbeddedResource (string name, ManifestResourceAttributes attributes, Stream stream) : base (name, attributes) { this.stream = stream; } internal EmbeddedResource (string name, ManifestResourceAttributes attributes, uint offset, MetadataReader reader) : base (name, attributes) { this.offset = offset; this.reader = reader; } public Stream GetResourceStream () { if (stream != null) return stream; if (data != null) return new MemoryStream (data); if (offset.HasValue) return reader.GetManagedResourceStream (offset.Value); throw new InvalidOperationException (); } public byte [] GetResourceData () { if (stream != null) return ReadStream (stream); if (data != null) return data; if (offset.HasValue) return reader.GetManagedResourceStream (offset.Value).ToArray (); throw new InvalidOperationException (); } static byte [] ReadStream (Stream stream) { var length = (int) stream.Length; var data = new byte [length]; int offset = 0, read; while ((read = stream.Read (data, offset, length - offset)) > 0) offset += read; return data; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/EventAttributes.cs ================================================ // // EventAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum EventAttributes : ushort { None = 0x0000, SpecialName = 0x0200, // Event is special RTSpecialName = 0x0400 // CLI provides 'special' behavior, depending upon the name of the event } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/EventDefinition.cs ================================================ // // EventDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using Mono.Collections.Generic; namespace Mono.Cecil { public sealed class EventDefinition : EventReference, IMemberDefinition { ushort attributes; Collection custom_attributes; internal MethodDefinition add_method; internal MethodDefinition invoke_method; internal MethodDefinition remove_method; internal Collection other_methods; public EventAttributes Attributes { get { return (EventAttributes) attributes; } set { attributes = (ushort) value; } } public MethodDefinition AddMethod { get { if (add_method != null) return add_method; InitializeMethods (); return add_method; } set { add_method = value; } } public MethodDefinition InvokeMethod { get { if (invoke_method != null) return invoke_method; InitializeMethods (); return invoke_method; } set { invoke_method = value; } } public MethodDefinition RemoveMethod { get { if (remove_method != null) return remove_method; InitializeMethods (); return remove_method; } set { remove_method = value; } } public bool HasOtherMethods { get { if (other_methods != null) return other_methods.Count > 0; InitializeMethods (); return !Mixin.IsNullOrEmpty (other_methods); } } public Collection OtherMethods { get { if (other_methods != null) return other_methods; InitializeMethods (); if (other_methods != null) return other_methods; return other_methods = new Collection (); } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return Mixin.GetHasCustomAttributes(this, Module); } } public Collection CustomAttributes { get { return custom_attributes ?? (Mixin.GetCustomAttributes(this, ref custom_attributes, Module)); } } #region EventAttributes public bool IsSpecialName { get { return Mixin.GetAttributes(attributes,(ushort) EventAttributes.SpecialName); } set { attributes =Mixin.SetAttributes(attributes,(ushort) EventAttributes.SpecialName, value); } } public bool IsRuntimeSpecialName { get { return Mixin.GetAttributes(attributes,(ushort) FieldAttributes.RTSpecialName); } set { attributes =Mixin.SetAttributes(attributes,(ushort) FieldAttributes.RTSpecialName, value); } } #endregion public new TypeDefinition DeclaringType { get { return (TypeDefinition) base.DeclaringType; } set { base.DeclaringType = value; } } public override bool IsDefinition { get { return true; } } public EventDefinition (string name, EventAttributes attributes, TypeReference eventType) : base (name, eventType) { this.attributes = (ushort) attributes; this.token = new MetadataToken (TokenType.Event); } void InitializeMethods () { var module = this.Module; lock (module.SyncRoot) { if (add_method != null || invoke_method != null || remove_method != null) return; if (!Mixin.HasImage(module)) return; module.Read (this, (@event, reader) => reader.ReadMethods (@event)); } } public override EventDefinition Resolve () { return this; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/EventReference.cs ================================================ // // EventReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { public abstract class EventReference : MemberReference { TypeReference event_type; public TypeReference EventType { get { return event_type; } set { event_type = value; } } public override string FullName { get { return event_type.FullName + " " + MemberFullName (); } } protected EventReference (string name, TypeReference eventType) : base (name) { if (eventType == null) throw new ArgumentNullException ("eventType"); event_type = eventType; } public abstract EventDefinition Resolve (); } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/ExportedType.cs ================================================ // // ExportedType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { public class ExportedType : IMetadataTokenProvider { string @namespace; string name; uint attributes; IMetadataScope scope; ModuleDefinition module; int identifier; ExportedType declaring_type; internal MetadataToken token; public string Namespace { get { return @namespace; } set { @namespace = value; } } public string Name { get { return name; } set { name = value; } } public TypeAttributes Attributes { get { return (TypeAttributes) attributes; } set { attributes = (uint) value; } } public IMetadataScope Scope { get { if (declaring_type != null) return declaring_type.Scope; return scope; } } public ExportedType DeclaringType { get { return declaring_type; } set { declaring_type = value; } } public MetadataToken MetadataToken { get { return token; } set { token = value; } } public int Identifier { get { return identifier; } set { identifier = value; } } #region TypeAttributes public bool IsNotPublic { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NotPublic); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NotPublic, value); } } public bool IsPublic { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.Public); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.Public, value); } } public bool IsNestedPublic { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPublic); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPublic, value); } } public bool IsNestedPrivate { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPrivate); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPrivate, value); } } public bool IsNestedFamily { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamily); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamily, value); } } public bool IsNestedAssembly { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedAssembly); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedAssembly, value); } } public bool IsNestedFamilyAndAssembly { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamANDAssem); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamANDAssem, value); } } public bool IsNestedFamilyOrAssembly { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamORAssem); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamORAssem, value); } } public bool IsAutoLayout { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.AutoLayout); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.AutoLayout, value); } } public bool IsSequentialLayout { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.SequentialLayout); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.SequentialLayout, value); } } public bool IsExplicitLayout { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.ExplicitLayout); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.ExplicitLayout, value); } } public bool IsClass { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Class); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Class, value); } } public bool IsInterface { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Interface); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Interface, value); } } public bool IsAbstract { get { return Mixin.GetAttributes(attributes,(uint) TypeAttributes.Abstract); } set { attributes =Mixin.SetAttributes(attributes,(uint) TypeAttributes.Abstract, value); } } public bool IsSealed { get { return Mixin.GetAttributes(attributes,(uint) TypeAttributes.Sealed); } set { attributes =Mixin.SetAttributes(attributes,(uint) TypeAttributes.Sealed, value); } } public bool IsSpecialName { get { return Mixin.GetAttributes(attributes,(uint) TypeAttributes.SpecialName); } set { attributes =Mixin.SetAttributes(attributes,(uint) TypeAttributes.SpecialName, value); } } public bool IsImport { get { return Mixin.GetAttributes(attributes,(uint) TypeAttributes.Import); } set { attributes =Mixin.SetAttributes(attributes,(uint) TypeAttributes.Import, value); } } public bool IsSerializable { get { return Mixin.GetAttributes(attributes,(uint) TypeAttributes.Serializable); } set { attributes =Mixin.SetAttributes(attributes,(uint) TypeAttributes.Serializable, value); } } public bool IsAnsiClass { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AnsiClass); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AnsiClass, value); } } public bool IsUnicodeClass { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.UnicodeClass); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.UnicodeClass, value); } } public bool IsAutoClass { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AutoClass); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AutoClass, value); } } public bool IsBeforeFieldInit { get { return Mixin.GetAttributes(attributes,(uint) TypeAttributes.BeforeFieldInit); } set { attributes =Mixin.SetAttributes(attributes,(uint) TypeAttributes.BeforeFieldInit, value); } } public bool IsRuntimeSpecialName { get { return Mixin.GetAttributes(attributes,(uint) TypeAttributes.RTSpecialName); } set { attributes =Mixin.SetAttributes(attributes,(uint) TypeAttributes.RTSpecialName, value); } } public bool HasSecurity { get { return Mixin.GetAttributes(attributes,(uint) TypeAttributes.HasSecurity); } set { attributes =Mixin.SetAttributes(attributes,(uint) TypeAttributes.HasSecurity, value); } } #endregion public bool IsForwarder { get { return Mixin.GetAttributes(attributes,(uint) TypeAttributes.Forwarder); } set { attributes =Mixin.SetAttributes(attributes,(uint) TypeAttributes.Forwarder, value); } } public string FullName { get { if (declaring_type != null) return declaring_type.FullName + "/" + name; if (string.IsNullOrEmpty (@namespace)) return name; return @namespace + "." + name; } } public ExportedType (string @namespace, string name, ModuleDefinition module, IMetadataScope scope) { this.@namespace = @namespace; this.name = name; this.scope = scope; this.module = module; } public override string ToString () { return FullName; } public TypeDefinition Resolve () { return module.Resolve (CreateReference ()); } internal TypeReference CreateReference () { return new TypeReference (@namespace, name, module, scope) { DeclaringType = declaring_type != null ? declaring_type.CreateReference () : null, }; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/FieldAttributes.cs ================================================ // // FieldAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum FieldAttributes : ushort { FieldAccessMask = 0x0007, CompilerControlled = 0x0000, // Member not referenceable Private = 0x0001, // Accessible only by the parent type FamANDAssem = 0x0002, // Accessible by sub-types only in this assembly Assembly = 0x0003, // Accessible by anyone in the Assembly Family = 0x0004, // Accessible only by type and sub-types FamORAssem = 0x0005, // Accessible by sub-types anywhere, plus anyone in the assembly Public = 0x0006, // Accessible by anyone who has visibility to this scope field contract attributes Static = 0x0010, // Defined on type, else per instance InitOnly = 0x0020, // Field may only be initialized, not written after init Literal = 0x0040, // Value is compile time constant NotSerialized = 0x0080, // Field does not have to be serialized when type is remoted SpecialName = 0x0200, // Field is special // Interop Attributes PInvokeImpl = 0x2000, // Implementation is forwarded through PInvoke // Additional flags RTSpecialName = 0x0400, // CLI provides 'special' behavior, depending upon the name of the field HasFieldMarshal = 0x1000, // Field has marshalling information HasDefault = 0x8000, // Field has default HasFieldRVA = 0x0100 // Field has RVA } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/FieldDefinition.cs ================================================ // // FieldDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using Mono.Collections.Generic; namespace Mono.Cecil { public sealed class FieldDefinition : FieldReference, IMemberDefinition, IConstantProvider, IMarshalInfoProvider { ushort attributes; Collection custom_attributes; int offset = Mixin.NotResolvedMarker; internal int rva = Mixin.NotResolvedMarker; byte [] initial_value; object constant = Mixin.NotResolved; MarshalInfo marshal_info; void ResolveLayout () { if (offset != Mixin.NotResolvedMarker) return; if (!HasImage) { offset = Mixin.NoDataMarker; return; } offset = Module.Read (this, (field, reader) => reader.ReadFieldLayout (field)); } public bool HasLayoutInfo { get { if (offset >= 0) return true; ResolveLayout (); return offset >= 0; } } public int Offset { get { if (offset >= 0) return offset; ResolveLayout (); return offset >= 0 ? offset : -1; } set { offset = value; } } void ResolveRVA () { if (rva != Mixin.NotResolvedMarker) return; if (!HasImage) return; rva = Module.Read (this, (field, reader) => reader.ReadFieldRVA (field)); } public int RVA { get { if (rva > 0) return rva; ResolveRVA (); return rva > 0 ? rva : 0; } } public byte [] InitialValue { get { if (initial_value != null) return initial_value; ResolveRVA (); if (initial_value == null) initial_value = Empty.Array; return initial_value; } set { initial_value = value; } } public FieldAttributes Attributes { get { return (FieldAttributes) attributes; } set { attributes = (ushort) value; } } public bool HasConstant { get { Mixin.ResolveConstant(this, ref constant, Module); return constant != Mixin.NoValue; } set { if (!value) constant = Mixin.NoValue; } } public object Constant { get { return HasConstant ? constant : null; } set { constant = value; } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return Mixin.GetHasCustomAttributes(this, Module); } } public Collection CustomAttributes { get { return custom_attributes ?? (Mixin.GetCustomAttributes(this, ref custom_attributes, Module)); } } public bool HasMarshalInfo { get { if (marshal_info != null) return true; return Mixin.GetHasMarshalInfo(this, Module); } } public MarshalInfo MarshalInfo { get { return marshal_info ?? (Mixin.GetMarshalInfo(this, ref marshal_info, Module)); } set { marshal_info = value; } } #region FieldAttributes public bool IsCompilerControlled { get { return Mixin.GetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.CompilerControlled); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.CompilerControlled, value); } } public bool IsPrivate { get { return Mixin.GetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Private); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Private, value); } } public bool IsFamilyAndAssembly { get { return Mixin.GetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.FamANDAssem); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.FamANDAssem, value); } } public bool IsAssembly { get { return Mixin.GetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Assembly); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Assembly, value); } } public bool IsFamily { get { return Mixin.GetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Family); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Family, value); } } public bool IsFamilyOrAssembly { get { return Mixin.GetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.FamORAssem); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.FamORAssem, value); } } public bool IsPublic { get { return Mixin.GetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Public); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Public, value); } } public bool IsStatic { get { return Mixin.GetAttributes(attributes,(ushort) FieldAttributes.Static); } set { attributes =Mixin.SetAttributes(attributes,(ushort) FieldAttributes.Static, value); } } public bool IsInitOnly { get { return Mixin.GetAttributes(attributes,(ushort) FieldAttributes.InitOnly); } set { attributes =Mixin.SetAttributes(attributes,(ushort) FieldAttributes.InitOnly, value); } } public bool IsLiteral { get { return Mixin.GetAttributes(attributes,(ushort) FieldAttributes.Literal); } set { attributes =Mixin.SetAttributes(attributes,(ushort) FieldAttributes.Literal, value); } } public bool IsNotSerialized { get { return Mixin.GetAttributes(attributes,(ushort) FieldAttributes.NotSerialized); } set { attributes =Mixin.SetAttributes(attributes,(ushort) FieldAttributes.NotSerialized, value); } } public bool IsSpecialName { get { return Mixin.GetAttributes(attributes,(ushort) FieldAttributes.SpecialName); } set { attributes =Mixin.SetAttributes(attributes,(ushort) FieldAttributes.SpecialName, value); } } public bool IsPInvokeImpl { get { return Mixin.GetAttributes(attributes,(ushort) FieldAttributes.PInvokeImpl); } set { attributes =Mixin.SetAttributes(attributes,(ushort) FieldAttributes.PInvokeImpl, value); } } public bool IsRuntimeSpecialName { get { return Mixin.GetAttributes(attributes,(ushort) FieldAttributes.RTSpecialName); } set { attributes =Mixin.SetAttributes(attributes,(ushort) FieldAttributes.RTSpecialName, value); } } public bool HasDefault { get { return Mixin.GetAttributes(attributes,(ushort) FieldAttributes.HasDefault); } set { attributes =Mixin.SetAttributes(attributes,(ushort) FieldAttributes.HasDefault, value); } } #endregion public override bool IsDefinition { get { return true; } } public new TypeDefinition DeclaringType { get { return (TypeDefinition) base.DeclaringType; } set { base.DeclaringType = value; } } public FieldDefinition (string name, FieldAttributes attributes, TypeReference fieldType) : base (name, fieldType) { this.attributes = (ushort) attributes; } public override FieldDefinition Resolve () { return this; } } static partial class Mixin { public const int NotResolvedMarker = -2; public const int NoDataMarker = -1; } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/FieldReference.cs ================================================ // // FieldReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { public class FieldReference : MemberReference { TypeReference field_type; public TypeReference FieldType { get { return field_type; } set { field_type = value; } } public override string FullName { get { return field_type.FullName + " " + MemberFullName (); } } internal override bool ContainsGenericParameter { get { return field_type.ContainsGenericParameter || base.ContainsGenericParameter; } } internal FieldReference () { this.token = new MetadataToken (TokenType.MemberRef); } public FieldReference (string name, TypeReference fieldType) : base (name) { if (fieldType == null) throw new ArgumentNullException ("fieldType"); this.field_type = fieldType; this.token = new MetadataToken (TokenType.MemberRef); } public FieldReference (string name, TypeReference fieldType, TypeReference declaringType) : this (name, fieldType) { if (declaringType == null) throw new ArgumentNullException("declaringType"); this.DeclaringType = declaringType; } public virtual FieldDefinition Resolve () { var module = this.Module; if (module == null) throw new NotSupportedException (); return module.Resolve (this); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/FileAttributes.cs ================================================ // // FileAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { enum FileAttributes : uint { ContainsMetaData = 0x0000, // This is not a resource file ContainsNoMetaData = 0x0001, // This is a resource file or other non-metadata-containing file } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/FunctionPointerType.cs ================================================ // // FunctionPointerType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Text; using Mono.Collections.Generic; using MD = Mono.Cecil.Metadata; namespace Mono.Cecil { public sealed class FunctionPointerType : TypeSpecification, IMethodSignature { readonly MethodReference function; public bool HasThis { get { return function.HasThis; } set { function.HasThis = value; } } public bool ExplicitThis { get { return function.ExplicitThis; } set { function.ExplicitThis = value; } } public MethodCallingConvention CallingConvention { get { return function.CallingConvention; } set { function.CallingConvention = value; } } public bool HasParameters { get { return function.HasParameters; } } public Collection Parameters { get { return function.Parameters; } } public TypeReference ReturnType { get { return function.MethodReturnType.ReturnType; } set { function.MethodReturnType.ReturnType = value; } } public MethodReturnType MethodReturnType { get { return function.MethodReturnType; } } public override string Name { get { return function.Name; } set { throw new InvalidOperationException (); } } public override string Namespace { get { return string.Empty; } set { throw new InvalidOperationException (); } } public override ModuleDefinition Module { get { return ReturnType.Module; } } public override IMetadataScope Scope { get { return function.ReturnType.Scope; } } public override bool IsFunctionPointer { get { return true; } } internal override bool ContainsGenericParameter { get { return function.ContainsGenericParameter; } } public override string FullName { get { var signature = new StringBuilder (); signature.Append (function.Name); signature.Append (" "); signature.Append (function.ReturnType.FullName); signature.Append (" *"); Mixin.MethodSignatureFullName (this,signature); return signature.ToString (); } } public FunctionPointerType () : base (null) { this.function = new MethodReference (); this.function.Name = "method"; this.etype = MD.ElementType.FnPtr; } public override TypeDefinition Resolve () { return null; } public override TypeReference GetElementType () { return this; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/GenericInstanceMethod.cs ================================================ // // GenericInstanceMethod.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Text; using Mono.Collections.Generic; namespace Mono.Cecil { public sealed class GenericInstanceMethod : MethodSpecification, IGenericInstance, IGenericContext { Collection arguments; public bool HasGenericArguments { get { return !Mixin.IsNullOrEmpty(arguments); } } public Collection GenericArguments { get { return arguments ?? (arguments = new Collection()); } } public override bool IsGenericInstance { get { return true; } } IGenericParameterProvider IGenericContext.Method { get { return ElementMethod; } } IGenericParameterProvider IGenericContext.Type { get { return ElementMethod.DeclaringType; } } internal override bool ContainsGenericParameter { get { return Mixin.ContainsGenericParameter(this) || base.ContainsGenericParameter; } } public override string FullName { get { var signature = new StringBuilder(); var method = this.ElementMethod; signature.Append(method.ReturnType.FullName) .Append(" ") .Append(method.DeclaringType.FullName) .Append("::") .Append(method.Name); Mixin.GenericInstanceFullName(this, signature); Mixin.MethodSignatureFullName(this, signature); return signature.ToString(); } } public GenericInstanceMethod(MethodReference method) : base(method) { } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/GenericInstanceType.cs ================================================ // // GenericInstanceType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Text; using Mono.Collections.Generic; using MD = Mono.Cecil.Metadata; namespace Mono.Cecil { public sealed class GenericInstanceType : TypeSpecification, IGenericInstance, IGenericContext { Collection arguments; public bool HasGenericArguments { get { return !Mixin.IsNullOrEmpty(arguments); } } public Collection GenericArguments { get { return arguments ?? (arguments = new Collection()); } } public override TypeReference DeclaringType { get { return ElementType.DeclaringType; } set { throw new NotSupportedException(); } } public override string FullName { get { var name = new StringBuilder(); name.Append(base.FullName); Mixin.GenericInstanceFullName(this, name); return name.ToString(); } } public override bool IsGenericInstance { get { return true; } } internal override bool ContainsGenericParameter { get { return Mixin.ContainsGenericParameter(this) || base.ContainsGenericParameter; } } IGenericParameterProvider IGenericContext.Type { get { return ElementType; } } public GenericInstanceType(TypeReference type) : base(type) { base.IsValueType = type.IsValueType; this.etype = MD.ElementType.GenericInst; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/GenericParameter.cs ================================================ // // GenericParameter.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Collections.Generic; using Mono.Cecil.Metadata; namespace Mono.Cecil { public sealed class GenericParameter : TypeReference, ICustomAttributeProvider { internal int position; internal GenericParameterType type; internal IGenericParameterProvider owner; ushort attributes; Collection constraints; Collection custom_attributes; public GenericParameterAttributes Attributes { get { return (GenericParameterAttributes) attributes; } set { attributes = (ushort) value; } } public int Position { get { return position; } } public GenericParameterType Type { get { return type; } } public IGenericParameterProvider Owner { get { return owner; } } public bool HasConstraints { get { if (constraints != null) return constraints.Count > 0; if (HasImage) return Module.Read (this, (generic_parameter, reader) => reader.HasGenericConstraints (generic_parameter)); return false; } } public Collection Constraints { get { if (constraints != null) return constraints; if (HasImage) return Module.Read (ref constraints, this, (generic_parameter, reader) => reader.ReadGenericConstraints (generic_parameter)); return constraints = new Collection (); } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return Mixin.GetHasCustomAttributes(this, Module); } } public Collection CustomAttributes { get { return custom_attributes ?? (Mixin.GetCustomAttributes(this, ref custom_attributes, Module)); } } public override IMetadataScope Scope { get { if (owner == null) return null; return owner.GenericParameterType == GenericParameterType.Method ? ((MethodReference) owner).DeclaringType.Scope : ((TypeReference) owner).Scope; } } public override ModuleDefinition Module { get { return module ?? owner.Module; } } public override string Name { get { if (!string.IsNullOrEmpty (base.Name)) return base.Name; return base.Name = (type == GenericParameterType.Method ? "!!" : "!") + position; } } public override string Namespace { get { return string.Empty; } set { throw new InvalidOperationException (); } } public override string FullName { get { return Name; } } public override bool IsGenericParameter { get { return true; } } internal override bool ContainsGenericParameter { get { return true; } } public override MetadataType MetadataType { get { return (MetadataType) etype; } } #region GenericParameterAttributes public bool IsNonVariant { get { return Mixin.GetMaskedAttributes(attributes,(ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.NonVariant); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.NonVariant, value); } } public bool IsCovariant { get { return Mixin.GetMaskedAttributes(attributes,(ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.Covariant); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.Covariant, value); } } public bool IsContravariant { get { return Mixin.GetMaskedAttributes(attributes,(ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.Contravariant); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.Contravariant, value); } } public bool HasReferenceTypeConstraint { get { return Mixin.GetAttributes(attributes,(ushort) GenericParameterAttributes.ReferenceTypeConstraint); } set { attributes =Mixin.SetAttributes(attributes,(ushort) GenericParameterAttributes.ReferenceTypeConstraint, value); } } public bool HasNotNullableValueTypeConstraint { get { return Mixin.GetAttributes(attributes,(ushort) GenericParameterAttributes.NotNullableValueTypeConstraint); } set { attributes =Mixin.SetAttributes(attributes,(ushort) GenericParameterAttributes.NotNullableValueTypeConstraint, value); } } public bool HasDefaultConstructorConstraint { get { return Mixin.GetAttributes(attributes,(ushort) GenericParameterAttributes.DefaultConstructorConstraint); } set { attributes =Mixin.SetAttributes(attributes,(ushort) GenericParameterAttributes.DefaultConstructorConstraint, value); } } #endregion public GenericParameter (IGenericParameterProvider owner) : this (string.Empty, owner) { } public GenericParameter (string name, IGenericParameterProvider owner) : base (string.Empty, name) { if (owner == null) throw new ArgumentNullException (); this.position = -1; this.owner = owner; this.type = owner.GenericParameterType; this.etype = ConvertGenericParameterType (this.type); } public GenericParameter (int position, GenericParameterType type, ModuleDefinition module) : base (string.Empty, string.Empty) { if (module == null) throw new ArgumentNullException (); this.position = position; this.type = type; this.etype = ConvertGenericParameterType (type); this.module = module; } static ElementType ConvertGenericParameterType (GenericParameterType type) { switch (type) { case GenericParameterType.Type: return ElementType.Var; case GenericParameterType.Method: return ElementType.MVar; } throw new ArgumentOutOfRangeException (); } public override TypeDefinition Resolve () { return null; } } sealed class GenericParameterCollection : Collection { readonly IGenericParameterProvider owner; internal GenericParameterCollection (IGenericParameterProvider owner) { this.owner = owner; } internal GenericParameterCollection (IGenericParameterProvider owner, int capacity) : base (capacity) { this.owner = owner; } protected override void OnAdd (GenericParameter item, int index) { UpdateGenericParameter (item, index); } protected override void OnInsert (GenericParameter item, int index) { UpdateGenericParameter (item, index); for (int i = index; i < size; i++) items[i].position = i + 1; } protected override void OnSet (GenericParameter item, int index) { UpdateGenericParameter (item, index); } void UpdateGenericParameter (GenericParameter item, int index) { item.owner = owner; item.position = index; item.type = owner.GenericParameterType; } protected override void OnRemove (GenericParameter item, int index) { item.owner = null; item.position = -1; item.type = GenericParameterType.Type; for (int i = index + 1; i < size; i++) items[i].position = i - 1; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/GenericParameterAttributes.cs ================================================ // // GenericParameterAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum GenericParameterAttributes : ushort { VarianceMask = 0x0003, NonVariant = 0x0000, Covariant = 0x0001, Contravariant = 0x0002, SpecialConstraintMask = 0x001c, ReferenceTypeConstraint = 0x0004, NotNullableValueTypeConstraint = 0x0008, DefaultConstructorConstraint = 0x0010 } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/IConstantProvider.cs ================================================ // // IConstantProvider.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public interface IConstantProvider : IMetadataTokenProvider { bool HasConstant { get; set; } object Constant { get; set; } } static partial class Mixin { internal static object NoValue = new object (); internal static object NotResolved = new object (); public static void ResolveConstant ( IConstantProvider self, ref object constant, ModuleDefinition module) { lock (module.SyncRoot) { if (constant != Mixin.NotResolved) return; if (Mixin.HasImage (module)) constant = module.Read (self, (provider, reader) => reader.ReadConstant (provider)); else constant = Mixin.NoValue; } } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/ICustomAttributeProvider.cs ================================================ // // ICustomAttributeProvider.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Collections.Generic; namespace Mono.Cecil { public interface ICustomAttributeProvider : IMetadataTokenProvider { Collection CustomAttributes { get; } bool HasCustomAttributes { get; } } static partial class Mixin { public static bool GetHasCustomAttributes( ICustomAttributeProvider self, ModuleDefinition module) { return Mixin.HasImage(module) && module.Read(self, (provider, reader) => reader.HasCustomAttributes(provider)); } public static Collection GetCustomAttributes( ICustomAttributeProvider self, ref Collection variable, ModuleDefinition module) { return Mixin.HasImage(module) ? module.Read(ref variable, self, (provider, reader) => reader.ReadCustomAttributes(provider)) : variable = new Collection(); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/IGenericInstance.cs ================================================ // // IGenericInstance.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System.Text; using Mono.Collections.Generic; namespace Mono.Cecil { public interface IGenericInstance : IMetadataTokenProvider { bool HasGenericArguments { get; } Collection GenericArguments { get; } } static partial class Mixin { public static bool ContainsGenericParameter (IGenericInstance self) { var arguments = self.GenericArguments; for (int i = 0; i < arguments.Count; i++) if (arguments [i].ContainsGenericParameter) return true; return false; } public static void GenericInstanceFullName (IGenericInstance self, StringBuilder builder) { builder.Append ("<"); var arguments = self.GenericArguments; for (int i = 0; i < arguments.Count; i++) { if (i > 0) builder.Append (","); builder.Append (arguments [i].FullName); } builder.Append (">"); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/IGenericParameterProvider.cs ================================================ // // IGenericParameterProvider.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using Mono.Collections.Generic; namespace Mono.Cecil { public interface IGenericParameterProvider : IMetadataTokenProvider { bool HasGenericParameters { get; } bool IsDefinition { get; } ModuleDefinition Module { get; } Collection GenericParameters { get; } GenericParameterType GenericParameterType { get; } } public enum GenericParameterType { Type, Method } interface IGenericContext { bool IsDefinition { get; } IGenericParameterProvider Type { get; } IGenericParameterProvider Method { get; } } static partial class Mixin { public static bool GetHasGenericParameters( IGenericParameterProvider self, ModuleDefinition module) { return Mixin.HasImage(module) && module.Read(self, (provider, reader) => reader.HasGenericParameters(provider)); } public static Collection GetGenericParameters( IGenericParameterProvider self, ref Collection collection, ModuleDefinition module) { return Mixin.HasImage(module) ? module.Read(ref collection, self, (provider, reader) => reader.ReadGenericParameters(provider)) : collection = new GenericParameterCollection(self); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/IMarshalInfoProvider.cs ================================================ // // IMarshalInfoProvider.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public interface IMarshalInfoProvider : IMetadataTokenProvider { bool HasMarshalInfo { get; } MarshalInfo MarshalInfo { get; set; } } static partial class Mixin { public static bool GetHasMarshalInfo( IMarshalInfoProvider self, ModuleDefinition module) { return Mixin.HasImage(module) && module.Read(self, (provider, reader) => reader.HasMarshalInfo(provider)); } public static MarshalInfo GetMarshalInfo( IMarshalInfoProvider self, ref MarshalInfo variable, ModuleDefinition module) { return Mixin.HasImage(module) ? module.Read(ref variable, self, (provider, reader) => reader.ReadMarshalInfo(provider)) : null; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/IMemberDefinition.cs ================================================ // // IMemberDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public interface IMemberDefinition : ICustomAttributeProvider { string Name { get; set; } string FullName { get; } bool IsSpecialName { get; set; } bool IsRuntimeSpecialName { get; set; } TypeDefinition DeclaringType { get; set; } } static partial class Mixin { public static bool GetAttributes(uint self, uint attributes) { return (self & attributes) != 0; } public static uint SetAttributes(uint self, uint attributes, bool value) { if (value) return self | attributes; return self & ~attributes; } public static bool GetMaskedAttributes(uint self, uint mask, uint attributes) { return (self & mask) == attributes; } public static uint SetMaskedAttributes(uint self, uint mask, uint attributes, bool value) { if (value) { self &= ~mask; return self | attributes; } return self & ~(mask & attributes); } public static bool GetAttributes(ushort self, ushort attributes) { return (self & attributes) != 0; } public static ushort SetAttributes(ushort self, ushort attributes, bool value) { if (value) return (ushort)(self | attributes); return (ushort)(self & ~attributes); } public static bool GetMaskedAttributes(ushort self, ushort mask, uint attributes) { return (self & mask) == attributes; } public static ushort SetMaskedAttributes(ushort self, ushort mask, uint attributes, bool value) { if (value) { self = (ushort)(self & ~mask); return (ushort)(self | attributes); } return (ushort)(self & ~(mask & attributes)); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/IMetadataScope.cs ================================================ // // IMetadataScope.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public enum MetadataScopeType { AssemblyNameReference, ModuleReference, ModuleDefinition, } public interface IMetadataScope : IMetadataTokenProvider { MetadataScopeType MetadataScopeType { get; } string Name { get; set; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/IMetadataTokenProvider.cs ================================================ // // IMetadataTokenProvider.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public interface IMetadataTokenProvider { MetadataToken MetadataToken { get; set; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/IMethodSignature.cs ================================================ // // IMethodSignature.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System.Text; using Mono.Collections.Generic; namespace Mono.Cecil { public interface IMethodSignature : IMetadataTokenProvider { bool HasThis { get; set; } bool ExplicitThis { get; set; } MethodCallingConvention CallingConvention { get; set; } bool HasParameters { get; } Collection Parameters { get; } TypeReference ReturnType { get; set; } MethodReturnType MethodReturnType { get; } } static partial class Mixin { public static bool HasImplicitThis (IMethodSignature self) { return self.HasThis && !self.ExplicitThis; } public static void MethodSignatureFullName (IMethodSignature self, StringBuilder builder) { builder.Append ("("); if (self.HasParameters) { var parameters = self.Parameters; for (int i = 0; i < parameters.Count; i++) { var parameter = parameters [i]; if (i > 0) builder.Append (","); if (parameter.ParameterType.IsSentinel) builder.Append ("...,"); builder.Append (parameter.ParameterType.FullName); } } builder.Append (")"); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/Import.cs ================================================ // // Import.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using SR = System.Reflection; using Mono.Cecil.Metadata; namespace Mono.Cecil { enum ImportGenericKind { Definition, Open, } class MetadataImporter { readonly ModuleDefinition module; public MetadataImporter(ModuleDefinition module) { this.module = module; } public TypeReference ImportType(TypeReference type, IGenericContext context) { if (Mixin.IsTypeSpecification(type)) return ImportTypeSpecification(type, context); var reference = new TypeReference( type.Namespace, type.Name, module, ImportScope(type.Scope), type.IsValueType); MetadataSystem.TryProcessPrimitiveTypeReference(reference); if (type.IsNested) reference.DeclaringType = ImportType(type.DeclaringType, context); if (type.HasGenericParameters) ImportGenericParameters(reference, type); return reference; } IMetadataScope ImportScope(IMetadataScope scope) { switch (scope.MetadataScopeType) { case MetadataScopeType.AssemblyNameReference: return ImportAssemblyName((AssemblyNameReference)scope); case MetadataScopeType.ModuleDefinition: return ImportAssemblyName(((ModuleDefinition)scope).Assembly.Name); case MetadataScopeType.ModuleReference: throw new NotImplementedException(); } throw new NotSupportedException(); } AssemblyNameReference ImportAssemblyName(AssemblyNameReference name) { AssemblyNameReference reference; if (TryGetAssemblyNameReference(name, out reference)) return reference; reference = new AssemblyNameReference(name.Name, name.Version) { Culture = name.Culture, HashAlgorithm = name.HashAlgorithm, }; var pk_token = !Mixin.IsNullOrEmpty(name.PublicKeyToken) ? new byte[name.PublicKeyToken.Length] : Empty.Array; if (pk_token.Length > 0) Buffer.BlockCopy(name.PublicKeyToken, 0, pk_token, 0, pk_token.Length); reference.PublicKeyToken = pk_token; module.AssemblyReferences.Add(reference); return reference; } bool TryGetAssemblyNameReference(AssemblyNameReference name_reference, out AssemblyNameReference assembly_reference) { var references = module.AssemblyReferences; for (int i = 0; i < references.Count; i++) { var reference = references[i]; if (name_reference.FullName != reference.FullName) // TODO compare field by field continue; assembly_reference = reference; return true; } assembly_reference = null; return false; } static void ImportGenericParameters(IGenericParameterProvider imported, IGenericParameterProvider original) { var parameters = original.GenericParameters; var imported_parameters = imported.GenericParameters; for (int i = 0; i < parameters.Count; i++) imported_parameters.Add(new GenericParameter(parameters[i].Name, imported)); } TypeReference ImportTypeSpecification(TypeReference type, IGenericContext context) { switch (type.etype) { case ElementType.SzArray: var vector = (ArrayType)type; return new ArrayType(ImportType(vector.ElementType, context)); case ElementType.Ptr: var pointer = (PointerType)type; return new PointerType(ImportType(pointer.ElementType, context)); case ElementType.ByRef: var byref = (ByReferenceType)type; return new ByReferenceType(ImportType(byref.ElementType, context)); case ElementType.Pinned: var pinned = (PinnedType)type; return new PinnedType(ImportType(pinned.ElementType, context)); case ElementType.Sentinel: var sentinel = (SentinelType)type; return new SentinelType(ImportType(sentinel.ElementType, context)); case ElementType.CModOpt: var modopt = (OptionalModifierType)type; return new OptionalModifierType( ImportType(modopt.ModifierType, context), ImportType(modopt.ElementType, context)); case ElementType.CModReqD: var modreq = (RequiredModifierType)type; return new RequiredModifierType( ImportType(modreq.ModifierType, context), ImportType(modreq.ElementType, context)); case ElementType.Array: var array = (ArrayType)type; var imported_array = new ArrayType(ImportType(array.ElementType, context)); if (array.IsVector) return imported_array; var dimensions = array.Dimensions; var imported_dimensions = imported_array.Dimensions; imported_dimensions.Clear(); for (int i = 0; i < dimensions.Count; i++) { var dimension = dimensions[i]; imported_dimensions.Add(new ArrayDimension(dimension.LowerBound, dimension.UpperBound)); } return imported_array; case ElementType.GenericInst: var instance = (GenericInstanceType)type; var element_type = ImportType(instance.ElementType, context); var imported_instance = new GenericInstanceType(element_type); var arguments = instance.GenericArguments; var imported_arguments = imported_instance.GenericArguments; for (int i = 0; i < arguments.Count; i++) imported_arguments.Add(ImportType(arguments[i], context)); return imported_instance; case ElementType.Var: if (context == null || context.Type == null) throw new InvalidOperationException(); return ((TypeReference)context.Type).GetElementType().GenericParameters[((GenericParameter)type).Position]; case ElementType.MVar: if (context == null || context.Method == null) throw new InvalidOperationException(); return context.Method.GenericParameters[((GenericParameter)type).Position]; } throw new NotSupportedException(type.etype.ToString()); } public FieldReference ImportField(FieldReference field, IGenericContext context) { var declaring_type = ImportType(field.DeclaringType, context); return new FieldReference { Name = field.Name, DeclaringType = declaring_type, FieldType = ImportType(field.FieldType, context ?? declaring_type), }; } public MethodReference ImportMethod(MethodReference method, IGenericContext context) { if (method.IsGenericInstance) return ImportMethodSpecification(method, context); var declaring_type = ImportType(method.DeclaringType, context); var reference = new MethodReference { Name = method.Name, HasThis = method.HasThis, ExplicitThis = method.ExplicitThis, DeclaringType = declaring_type, }; reference.CallingConvention = method.CallingConvention; if (method.HasGenericParameters) ImportGenericParameters(reference, method); reference.ReturnType = ImportType(method.ReturnType, context ?? reference); if (!method.HasParameters) return reference; var reference_parameters = reference.Parameters; var parameters = method.Parameters; for (int i = 0; i < parameters.Count; i++) reference_parameters.Add( new ParameterDefinition(ImportType(parameters[i].ParameterType, context ?? reference))); return reference; } MethodSpecification ImportMethodSpecification(MethodReference method, IGenericContext context) { if (!method.IsGenericInstance) throw new NotSupportedException(); var instance = (GenericInstanceMethod)method; var element_method = ImportMethod(instance.ElementMethod, context); var imported_instance = new GenericInstanceMethod(element_method); var arguments = instance.GenericArguments; var imported_arguments = imported_instance.GenericArguments; for (int i = 0; i < arguments.Count; i++) imported_arguments.Add(ImportType(arguments[i], context)); return imported_instance; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/LinkedResource.cs ================================================ // // LinkedResource.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public sealed class LinkedResource : Resource { internal byte [] hash; string file; public byte [] Hash { get { return hash; } } public string File { get { return file; } set { file = value; } } public override ResourceType ResourceType { get { return ResourceType.Linked; } } public LinkedResource (string name, ManifestResourceAttributes flags) : base (name, flags) { } public LinkedResource (string name, ManifestResourceAttributes flags, string file) : base (name, flags) { this.file = file; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/ManifestResourceAttributes.cs ================================================ // // ManifestResourceAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum ManifestResourceAttributes : uint { VisibilityMask = 0x0007, Public = 0x0001, // The resource is exported from the Assembly Private = 0x0002 // The resource is private to the Assembly } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/MarshalInfo.cs ================================================ // // MarshalInfo.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { public class MarshalInfo { internal NativeType native; public NativeType NativeType { get { return native; } set { native = value; } } public MarshalInfo (NativeType native) { this.native = native; } } public sealed class ArrayMarshalInfo : MarshalInfo { internal NativeType element_type; internal int size_parameter_index; internal int size; internal int size_parameter_multiplier; public NativeType ElementType { get { return element_type; } set { element_type = value; } } public int SizeParameterIndex { get { return size_parameter_index; } set { size_parameter_index = value; } } public int Size { get { return size; } set { size = value; } } public int SizeParameterMultiplier { get { return size_parameter_multiplier; } set { size_parameter_multiplier = value; } } public ArrayMarshalInfo () : base (NativeType.Array) { element_type = NativeType.None; size_parameter_index = -1; size = -1; size_parameter_multiplier = -1; } } public sealed class CustomMarshalInfo : MarshalInfo { internal Guid guid; internal string unmanaged_type; internal TypeReference managed_type; internal string cookie; public Guid Guid { get { return guid; } set { guid = value; } } public string UnmanagedType { get { return unmanaged_type; } set { unmanaged_type = value; } } public TypeReference ManagedType { get { return managed_type; } set { managed_type = value; } } public string Cookie { get { return cookie; } set { cookie = value; } } public CustomMarshalInfo () : base (NativeType.CustomMarshaler) { } } public sealed class SafeArrayMarshalInfo : MarshalInfo { internal VariantType element_type; public VariantType ElementType { get { return element_type; } set { element_type = value; } } public SafeArrayMarshalInfo () : base (NativeType.SafeArray) { element_type = VariantType.None; } } public sealed class FixedArrayMarshalInfo : MarshalInfo { internal NativeType element_type; internal int size; public NativeType ElementType { get { return element_type; } set { element_type = value; } } public int Size { get { return size; } set { size = value; } } public FixedArrayMarshalInfo () : base (NativeType.FixedArray) { element_type = NativeType.None; } } public sealed class FixedSysStringMarshalInfo : MarshalInfo { internal int size; public int Size { get { return size; } set { size = value; } } public FixedSysStringMarshalInfo () : base (NativeType.FixedSysString) { size = -1; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/MemberDefinitionCollection.cs ================================================ // // MemberDefinitionCollection.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Collections.Generic; namespace Mono.Cecil { class MemberDefinitionCollection : Collection where T : IMemberDefinition { TypeDefinition container; internal MemberDefinitionCollection (TypeDefinition container) { this.container = container; } internal MemberDefinitionCollection (TypeDefinition container, int capacity) : base (capacity) { this.container = container; } protected override void OnAdd (T item, int index) { Attach (item); } protected sealed override void OnSet (T item, int index) { Attach (item); } protected sealed override void OnInsert (T item, int index) { Attach (item); } protected sealed override void OnRemove (T item, int index) { Detach (item); } protected sealed override void OnClear () { foreach (var definition in this) Detach (definition); } void Attach (T element) { if (element.DeclaringType == container) return; if (element.DeclaringType != null) throw new ArgumentException ("Member already attached"); element.DeclaringType = this.container; } static void Detach (T element) { element.DeclaringType = null; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/MemberReference.cs ================================================ // // MemberReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public abstract class MemberReference : IMetadataTokenProvider { string name; TypeReference declaring_type; internal MetadataToken token; public virtual string Name { get { return name; } set { name = value; } } public abstract string FullName { get; } public virtual TypeReference DeclaringType { get { return declaring_type; } set { declaring_type = value; } } public MetadataToken MetadataToken { get { return token; } set { token = value; } } internal bool HasImage { get { var module = Module; if (module == null) return false; return module.HasImage; } } public virtual ModuleDefinition Module { get { return declaring_type != null ? declaring_type.Module : null; } } public virtual bool IsDefinition { get { return false; } } internal virtual bool ContainsGenericParameter { get { return declaring_type != null && declaring_type.ContainsGenericParameter; } } internal MemberReference () { } internal MemberReference (string name) { this.name = name ?? string.Empty; } internal string MemberFullName () { if (declaring_type == null) return name; return declaring_type.FullName + "::" + name; } public override string ToString () { return FullName; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/MetadataResolver.cs ================================================ // // MetadataResolver.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Collections.Generic; namespace Mono.Cecil { public interface IAssemblyResolver { AssemblyDefinition Resolve(AssemblyNameReference name); AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters); AssemblyDefinition Resolve(string fullName); AssemblyDefinition Resolve(string fullName, ReaderParameters parameters); event AssemblyResolveEventHandler ResolveFailure; } public interface IMetadataResolver { TypeDefinition Resolve(TypeReference type); FieldDefinition Resolve(FieldReference field); MethodDefinition Resolve(MethodReference method); } public class ResolutionException : Exception { readonly MemberReference member; public MemberReference Member { get { return member; } } public ResolutionException(MemberReference member) : base("Failed to resolve " + member.FullName) { this.member = member; } } public class MetadataResolver : IMetadataResolver { readonly IAssemblyResolver assembly_resolver; public IAssemblyResolver AssemblyResolver { get { return assembly_resolver; } } public MetadataResolver(IAssemblyResolver assemblyResolver) { if (assemblyResolver == null) throw new ArgumentNullException("assemblyResolver"); assembly_resolver = assemblyResolver; } public virtual TypeDefinition Resolve(TypeReference type) { if (type == null) throw new ArgumentNullException("type"); type = type.GetElementType(); var scope = type.Scope; switch (scope.MetadataScopeType) { case MetadataScopeType.AssemblyNameReference: var assembly = assembly_resolver.Resolve((AssemblyNameReference)scope); if (assembly == null) return null; return GetType(assembly.MainModule, type); case MetadataScopeType.ModuleDefinition: return GetType((ModuleDefinition)scope, type); case MetadataScopeType.ModuleReference: var modules = type.Module.Assembly.Modules; var module_ref = (ModuleReference)scope; for (int i = 0; i < modules.Count; i++) { var netmodule = modules[i]; if (netmodule.Name == module_ref.Name) return GetType(netmodule, type); } break; } throw new NotSupportedException(); } static TypeDefinition GetType(ModuleDefinition module, TypeReference reference) { var type = GetTypeDefinition(module, reference); if (type != null) return type; if (!module.HasExportedTypes) return null; var exported_types = module.ExportedTypes; for (int i = 0; i < exported_types.Count; i++) { var exported_type = exported_types[i]; if (exported_type.Name != reference.Name) continue; if (exported_type.Namespace != reference.Namespace) continue; return exported_type.Resolve(); } return null; } static TypeDefinition GetTypeDefinition(ModuleDefinition module, TypeReference type) { if (!type.IsNested) return module.GetType(type.Namespace, type.Name); var declaring_type = type.DeclaringType.Resolve(); if (declaring_type == null) return null; return Mixin.GetNestedType(declaring_type, type.Name); } public virtual FieldDefinition Resolve(FieldReference field) { if (field == null) throw new ArgumentNullException("field"); var type = Resolve(field.DeclaringType); if (type == null) return null; if (!type.HasFields) return null; return GetField(type, field); } FieldDefinition GetField(TypeDefinition type, FieldReference reference) { while (type != null) { var field = GetField(type.Fields, reference); if (field != null) return field; if (type.BaseType == null) return null; type = Resolve(type.BaseType); } return null; } static FieldDefinition GetField(Collection fields, FieldReference reference) { for (int i = 0; i < fields.Count; i++) { var field = fields[i]; if (field.Name != reference.Name) continue; if (!AreSame(field.FieldType, reference.FieldType)) continue; return field; } return null; } public virtual MethodDefinition Resolve(MethodReference method) { if (method == null) throw new ArgumentNullException("method"); var type = Resolve(method.DeclaringType); if (type == null) return null; method = method.GetElementMethod(); if (!type.HasMethods) return null; return GetMethod(type, method); } MethodDefinition GetMethod(TypeDefinition type, MethodReference reference) { while (type != null) { var method = GetMethod(type.Methods, reference); if (method != null) return method; if (type.BaseType == null) return null; type = Resolve(type.BaseType); } return null; } public static MethodDefinition GetMethod(Collection methods, MethodReference reference) { for (int i = 0; i < methods.Count; i++) { var method = methods[i]; if (method.Name != reference.Name) continue; if (method.HasGenericParameters != reference.HasGenericParameters) continue; if (method.HasGenericParameters && method.GenericParameters.Count != reference.GenericParameters.Count) continue; if (!AreSame(method.ReturnType, reference.ReturnType)) continue; if (method.HasParameters != reference.HasParameters) continue; if (!method.HasParameters && !reference.HasParameters) return method; if (!AreSame(method.Parameters, reference.Parameters)) continue; return method; } return null; } static bool AreSame(Collection a, Collection b) { var count = a.Count; if (count != b.Count) return false; if (count == 0) return true; for (int i = 0; i < count; i++) if (!AreSame(a[i].ParameterType, b[i].ParameterType)) return false; return true; } static bool AreSame(TypeSpecification a, TypeSpecification b) { if (!AreSame(a.ElementType, b.ElementType)) return false; if (a.IsGenericInstance) return AreSame((GenericInstanceType)a, (GenericInstanceType)b); if (a.IsRequiredModifier || a.IsOptionalModifier) return AreSame((IModifierType)a, (IModifierType)b); if (a.IsArray) return AreSame((ArrayType)a, (ArrayType)b); return true; } static bool AreSame(ArrayType a, ArrayType b) { if (a.Rank != b.Rank) return false; // TODO: dimensions return true; } static bool AreSame(IModifierType a, IModifierType b) { return AreSame(a.ModifierType, b.ModifierType); } static bool AreSame(GenericInstanceType a, GenericInstanceType b) { if (a.GenericArguments.Count != b.GenericArguments.Count) return false; for (int i = 0; i < a.GenericArguments.Count; i++) if (!AreSame(a.GenericArguments[i], b.GenericArguments[i])) return false; return true; } static bool AreSame(GenericParameter a, GenericParameter b) { return a.Position == b.Position; } static bool AreSame(TypeReference a, TypeReference b) { if (ReferenceEquals(a, b)) return true; if (a == null || b == null) return false; if (a.etype != b.etype) return false; if (a.IsGenericParameter) return AreSame((GenericParameter)a, (GenericParameter)b); if (Mixin.IsTypeSpecification(a)) return AreSame((TypeSpecification)a, (TypeSpecification)b); if (a.Name != b.Name || a.Namespace != b.Namespace) return false; //TODO: check scope return AreSame(a.DeclaringType, b.DeclaringType); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/MetadataSystem.cs ================================================ // // MetadataSystem.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using Mono.Cecil.Metadata; namespace Mono.Cecil { struct Range { public uint Start; public uint Length; public Range (uint index, uint length) { this.Start = index; this.Length = length; } } sealed class MetadataSystem { internal AssemblyNameReference [] AssemblyReferences; internal ModuleReference [] ModuleReferences; internal TypeDefinition [] Types; internal TypeReference [] TypeReferences; internal FieldDefinition [] Fields; internal MethodDefinition [] Methods; internal MemberReference [] MemberReferences; internal Dictionary NestedTypes; internal Dictionary ReverseNestedTypes; internal Dictionary Interfaces; internal Dictionary> ClassLayouts; internal Dictionary FieldLayouts; internal Dictionary FieldRVAs; internal Dictionary FieldMarshals; internal Dictionary> Constants; internal Dictionary Overrides; internal Dictionary CustomAttributes; internal Dictionary SecurityDeclarations; internal Dictionary Events; internal Dictionary Properties; internal Dictionary> Semantics; internal Dictionary> PInvokes; internal Dictionary GenericParameters; internal Dictionary GenericConstraints; static Dictionary> primitive_value_types; static void InitializePrimitives () { primitive_value_types = new Dictionary> (18, StringComparer.Ordinal) { { "Void", new Row (ElementType.Void, false) }, { "Boolean", new Row (ElementType.Boolean, true) }, { "Char", new Row (ElementType.Char, true) }, { "SByte", new Row (ElementType.I1, true) }, { "Byte", new Row (ElementType.U1, true) }, { "Int16", new Row (ElementType.I2, true) }, { "UInt16", new Row (ElementType.U2, true) }, { "Int32", new Row (ElementType.I4, true) }, { "UInt32", new Row (ElementType.U4, true) }, { "Int64", new Row (ElementType.I8, true) }, { "UInt64", new Row (ElementType.U8, true) }, { "Single", new Row (ElementType.R4, true) }, { "Double", new Row (ElementType.R8, true) }, { "String", new Row (ElementType.String, false) }, { "TypedReference", new Row (ElementType.TypedByRef, false) }, { "IntPtr", new Row (ElementType.I, true) }, { "UIntPtr", new Row (ElementType.U, true) }, { "Object", new Row (ElementType.Object, false) }, }; } public static void TryProcessPrimitiveTypeReference (TypeReference type) { if (type.Namespace != "System") return; var scope = type.scope; if (scope == null || scope.MetadataScopeType != MetadataScopeType.AssemblyNameReference) return; Row primitive_data; if (!TryGetPrimitiveData (type, out primitive_data)) return; type.etype = primitive_data.Col1; type.IsValueType = primitive_data.Col2; } public static bool TryGetPrimitiveElementType (TypeDefinition type, out ElementType etype) { etype = ElementType.None; if (type.Namespace != "System") return false; Row primitive_data; if (TryGetPrimitiveData (type, out primitive_data) &&Mixin .IsPrimitive (primitive_data.Col1)) { etype = primitive_data.Col1; return true; } return false; } static bool TryGetPrimitiveData (TypeReference type, out Row primitive_data) { if (primitive_value_types == null) InitializePrimitives (); return primitive_value_types.TryGetValue (type.Name, out primitive_data); } public void Clear () { if (NestedTypes != null) NestedTypes.Clear (); if (ReverseNestedTypes != null) ReverseNestedTypes.Clear (); if (Interfaces != null) Interfaces.Clear (); if (ClassLayouts != null) ClassLayouts.Clear (); if (FieldLayouts != null) FieldLayouts.Clear (); if (FieldRVAs != null) FieldRVAs.Clear (); if (FieldMarshals != null) FieldMarshals.Clear (); if (Constants != null) Constants.Clear (); if (Overrides != null) Overrides.Clear (); if (CustomAttributes != null) CustomAttributes.Clear (); if (SecurityDeclarations != null) SecurityDeclarations.Clear (); if (Events != null) Events.Clear (); if (Properties != null) Properties.Clear (); if (Semantics != null) Semantics.Clear (); if (PInvokes != null) PInvokes.Clear (); if (GenericParameters != null) GenericParameters.Clear (); if (GenericConstraints != null) GenericConstraints.Clear (); } public TypeDefinition GetTypeDefinition (uint rid) { if (rid < 1 || rid > Types.Length) return null; return Types [rid - 1]; } public void AddTypeDefinition (TypeDefinition type) { Types [type.token.RID - 1] = type; } public TypeReference GetTypeReference (uint rid) { if (rid < 1 || rid > TypeReferences.Length) return null; return TypeReferences [rid - 1]; } public void AddTypeReference (TypeReference type) { TypeReferences [type.token.RID - 1] = type; } public FieldDefinition GetFieldDefinition (uint rid) { if (rid < 1 || rid > Fields.Length) return null; return Fields [rid - 1]; } public void AddFieldDefinition (FieldDefinition field) { Fields [field.token.RID - 1] = field; } public MethodDefinition GetMethodDefinition (uint rid) { if (rid < 1 || rid > Methods.Length) return null; return Methods [rid - 1]; } public void AddMethodDefinition (MethodDefinition method) { Methods [method.token.RID - 1] = method; } public MemberReference GetMemberReference (uint rid) { if (rid < 1 || rid > MemberReferences.Length) return null; return MemberReferences [rid - 1]; } public void AddMemberReference (MemberReference member) { MemberReferences [member.token.RID - 1] = member; } public bool TryGetNestedTypeMapping (TypeDefinition type, out uint [] mapping) { return NestedTypes.TryGetValue (type.token.RID, out mapping); } public void SetNestedTypeMapping (uint type_rid, uint [] mapping) { NestedTypes [type_rid] = mapping; } public void RemoveNestedTypeMapping (TypeDefinition type) { NestedTypes.Remove (type.token.RID); } public bool TryGetReverseNestedTypeMapping (TypeDefinition type, out uint declaring) { return ReverseNestedTypes.TryGetValue (type.token.RID, out declaring); } public void SetReverseNestedTypeMapping (uint nested, uint declaring) { ReverseNestedTypes.Add (nested, declaring); } public void RemoveReverseNestedTypeMapping (TypeDefinition type) { ReverseNestedTypes.Remove (type.token.RID); } public bool TryGetInterfaceMapping (TypeDefinition type, out MetadataToken [] mapping) { return Interfaces.TryGetValue (type.token.RID, out mapping); } public void SetInterfaceMapping (uint type_rid, MetadataToken [] mapping) { Interfaces [type_rid] = mapping; } public void RemoveInterfaceMapping (TypeDefinition type) { Interfaces.Remove (type.token.RID); } public void AddPropertiesRange (uint type_rid, Range range) { Properties.Add (type_rid, range); } public bool TryGetPropertiesRange (TypeDefinition type, out Range range) { return Properties.TryGetValue (type.token.RID, out range); } public void RemovePropertiesRange (TypeDefinition type) { Properties.Remove (type.token.RID); } public void AddEventsRange (uint type_rid, Range range) { Events.Add (type_rid, range); } public bool TryGetEventsRange (TypeDefinition type, out Range range) { return Events.TryGetValue (type.token.RID, out range); } public void RemoveEventsRange (TypeDefinition type) { Events.Remove (type.token.RID); } public bool TryGetGenericParameterRange (IGenericParameterProvider owner, out Range range) { return GenericParameters.TryGetValue (owner.MetadataToken, out range); } public void RemoveGenericParameterRange (IGenericParameterProvider owner) { GenericParameters.Remove (owner.MetadataToken); } public bool TryGetCustomAttributeRange (ICustomAttributeProvider owner, out Range range) { return CustomAttributes.TryGetValue (owner.MetadataToken, out range); } public void RemoveCustomAttributeRange (ICustomAttributeProvider owner) { CustomAttributes.Remove (owner.MetadataToken); } public bool TryGetSecurityDeclarationRange (ISecurityDeclarationProvider owner, out Range range) { return SecurityDeclarations.TryGetValue (owner.MetadataToken, out range); } public void RemoveSecurityDeclarationRange (ISecurityDeclarationProvider owner) { SecurityDeclarations.Remove (owner.MetadataToken); } public bool TryGetGenericConstraintMapping (GenericParameter generic_parameter, out MetadataToken [] mapping) { return GenericConstraints.TryGetValue (generic_parameter.token.RID, out mapping); } public void SetGenericConstraintMapping (uint gp_rid, MetadataToken [] mapping) { GenericConstraints [gp_rid] = mapping; } public void RemoveGenericConstraintMapping (GenericParameter generic_parameter) { GenericConstraints.Remove (generic_parameter.token.RID); } public bool TryGetOverrideMapping (MethodDefinition method, out MetadataToken [] mapping) { return Overrides.TryGetValue (method.token.RID, out mapping); } public void SetOverrideMapping (uint rid, MetadataToken [] mapping) { Overrides [rid] = mapping; } public void RemoveOverrideMapping (MethodDefinition method) { Overrides.Remove (method.token.RID); } public TypeDefinition GetFieldDeclaringType (uint field_rid) { return BinaryRangeSearch (Types, field_rid, true); } public TypeDefinition GetMethodDeclaringType (uint method_rid) { return BinaryRangeSearch (Types, method_rid, false); } static TypeDefinition BinaryRangeSearch (TypeDefinition [] types, uint rid, bool field) { int min = 0; int max = types.Length - 1; while (min <= max) { int mid = min + ((max - min) / 2); var type = types [mid]; var range = field ? type.fields_range : type.methods_range; if (rid < range.Start) max = mid - 1; else if (rid >= range.Start + range.Length) min = mid + 1; else return type; } return null; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/MethodAttributes.cs ================================================ // // MethodAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum MethodAttributes : ushort { MemberAccessMask = 0x0007, CompilerControlled = 0x0000, // Member not referenceable Private = 0x0001, // Accessible only by the parent type FamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly Assembly = 0x0003, // Accessibly by anyone in the Assembly Family = 0x0004, // Accessible only by type and sub-types FamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly Public = 0x0006, // Accessibly by anyone who has visibility to this scope Static = 0x0010, // Defined on type, else per instance Final = 0x0020, // Method may not be overridden Virtual = 0x0040, // Method is virtual HideBySig = 0x0080, // Method hides by name+sig, else just by name VtableLayoutMask = 0x0100, // Use this mask to retrieve vtable attributes ReuseSlot = 0x0000, // Method reuses existing slot in vtable NewSlot = 0x0100, // Method always gets a new slot in the vtable CheckAccessOnOverride = 0x0200, // Method can only be overriden if also accessible Abstract = 0x0400, // Method does not provide an implementation SpecialName = 0x0800, // Method is special // Interop Attributes PInvokeImpl = 0x2000, // Implementation is forwarded through PInvoke UnmanagedExport = 0x0008, // Reserved: shall be zero for conforming implementations // Additional flags RTSpecialName = 0x1000, // CLI provides 'special' behavior, depending upon the name of the method HasSecurity = 0x4000, // Method has security associate with it RequireSecObject = 0x8000 // Method calls another method containing security code } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/MethodCallingConvention.cs ================================================ // // MethodCallingConvention.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public enum MethodCallingConvention : byte { Default = 0x0, C = 0x1, StdCall = 0x2, ThisCall = 0x3, FastCall = 0x4, VarArg = 0x5, Generic = 0x10, } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/MethodDefinition.cs ================================================ // // MethodDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using Mono.Cecil.Cil; using Mono.Collections.Generic; using RVA = System.UInt32; namespace Mono.Cecil { public sealed class MethodDefinition : MethodReference, IMemberDefinition, ISecurityDeclarationProvider { ushort attributes; ushort impl_attributes; internal volatile bool sem_attrs_ready; internal MethodSemanticsAttributes sem_attrs; Collection custom_attributes; Collection security_declarations; internal RVA rva; internal PInvokeInfo pinvoke; Collection overrides; internal MethodBody body; public MethodAttributes Attributes { get { return (MethodAttributes)attributes; } set { attributes = (ushort)value; } } public MethodImplAttributes ImplAttributes { get { return (MethodImplAttributes)impl_attributes; } set { impl_attributes = (ushort)value; } } public MethodSemanticsAttributes SemanticsAttributes { get { if (sem_attrs_ready) return sem_attrs; if (HasImage) { ReadSemantics(); return sem_attrs; } sem_attrs = MethodSemanticsAttributes.None; sem_attrs_ready = true; return sem_attrs; } set { sem_attrs = value; } } internal void ReadSemantics() { if (sem_attrs_ready) return; var module = this.Module; if (module == null) return; if (!module.HasImage) return; module.Read(this, (method, reader) => reader.ReadAllSemantics(method)); } public bool HasSecurityDeclarations { get { if (security_declarations != null) return security_declarations.Count > 0; return Mixin.GetHasSecurityDeclarations(this, Module); } } public Collection SecurityDeclarations { get { return security_declarations ?? (Mixin.GetSecurityDeclarations(this, ref security_declarations, Module)); } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return Mixin.GetHasCustomAttributes(this, Module); } } public Collection CustomAttributes { get { return custom_attributes ?? (Mixin.GetCustomAttributes(this, ref custom_attributes, Module)); } } public int RVA { get { return (int)rva; } } public bool HasBody { get { return (attributes & (ushort)MethodAttributes.Abstract) == 0 && (attributes & (ushort)MethodAttributes.PInvokeImpl) == 0 && (impl_attributes & (ushort)MethodImplAttributes.InternalCall) == 0 && (impl_attributes & (ushort)MethodImplAttributes.Native) == 0 && (impl_attributes & (ushort)MethodImplAttributes.Unmanaged) == 0 && (impl_attributes & (ushort)MethodImplAttributes.Runtime) == 0; } } public MethodBody Body { get { MethodBody localBody = this.body; if (localBody != null) return localBody; if (!HasBody) return null; if (HasImage && rva != 0) return Module.Read(ref body, this, (method, reader) => reader.ReadMethodBody(method)); return body = new MethodBody(this); } set { // we reset Body to null in ILSpy to save memory; so we need that operation to be thread-safe lock (Module.SyncRoot) { body = value; } } } public bool HasPInvokeInfo { get { if (pinvoke != null) return true; return IsPInvokeImpl; } } public PInvokeInfo PInvokeInfo { get { if (pinvoke != null) return pinvoke; if (HasImage && IsPInvokeImpl) return Module.Read(ref pinvoke, this, (method, reader) => reader.ReadPInvokeInfo(method)); return null; } set { IsPInvokeImpl = true; pinvoke = value; } } public bool HasOverrides { get { if (overrides != null) return overrides.Count > 0; if (HasImage) return Module.Read(this, (method, reader) => reader.HasOverrides(method)); return false; } } public Collection Overrides { get { if (overrides != null) return overrides; if (HasImage) return Module.Read(ref overrides, this, (method, reader) => reader.ReadOverrides(method)); return overrides = new Collection(); } } public override bool HasGenericParameters { get { if (generic_parameters != null) return generic_parameters.Count > 0; return Mixin.GetHasGenericParameters(this, Module); } } public override Collection GenericParameters { get { return generic_parameters ?? (Mixin.GetGenericParameters(this, ref generic_parameters, Module)); } } #region MethodAttributes public bool IsCompilerControlled { get { return Mixin.GetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.CompilerControlled); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.CompilerControlled, value); } } public bool IsPrivate { get { return Mixin.GetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Private); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Private, value); } } public bool IsFamilyAndAssembly { get { return Mixin.GetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.FamANDAssem); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.FamANDAssem, value); } } public bool IsAssembly { get { return Mixin.GetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Assembly); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Assembly, value); } } public bool IsFamily { get { return Mixin.GetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Family); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Family, value); } } public bool IsFamilyOrAssembly { get { return Mixin.GetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.FamORAssem); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.FamORAssem, value); } } public bool IsPublic { get { return Mixin.GetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Public); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Public, value); } } public bool IsStatic { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.Static); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.Static, value); } } public bool IsFinal { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.Final); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.Final, value); } } public bool IsVirtual { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.Virtual); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.Virtual, value); } } public bool IsHideBySig { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.HideBySig); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.HideBySig, value); } } public bool IsReuseSlot { get { return Mixin.GetMaskedAttributes(attributes,(ushort)MethodAttributes.VtableLayoutMask, (ushort)MethodAttributes.ReuseSlot); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort)MethodAttributes.VtableLayoutMask, (ushort)MethodAttributes.ReuseSlot, value); } } public bool IsNewSlot { get { return Mixin.GetMaskedAttributes(attributes,(ushort)MethodAttributes.VtableLayoutMask, (ushort)MethodAttributes.NewSlot); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort)MethodAttributes.VtableLayoutMask, (ushort)MethodAttributes.NewSlot, value); } } public bool IsCheckAccessOnOverride { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.CheckAccessOnOverride); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.CheckAccessOnOverride, value); } } public bool IsAbstract { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.Abstract); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.Abstract, value); } } public bool IsSpecialName { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.SpecialName); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.SpecialName, value); } } public bool IsPInvokeImpl { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.PInvokeImpl); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.PInvokeImpl, value); } } public bool IsUnmanagedExport { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.UnmanagedExport); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.UnmanagedExport, value); } } public bool IsRuntimeSpecialName { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.RTSpecialName); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.RTSpecialName, value); } } public bool HasSecurity { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.HasSecurity); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.HasSecurity, value); } } #endregion #region MethodImplAttributes public bool IsIL { get { return Mixin.GetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.CodeTypeMask, (ushort)MethodImplAttributes.IL); } set { impl_attributes = Mixin.SetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.CodeTypeMask, (ushort)MethodImplAttributes.IL, value); } } public bool IsNative { get { return Mixin.GetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.CodeTypeMask, (ushort)MethodImplAttributes.Native); } set { impl_attributes = Mixin.SetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.CodeTypeMask, (ushort)MethodImplAttributes.Native, value); } } public bool IsRuntime { get { return Mixin.GetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.CodeTypeMask, (ushort)MethodImplAttributes.Runtime); } set { impl_attributes = Mixin.SetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.CodeTypeMask, (ushort)MethodImplAttributes.Runtime, value); } } public bool IsUnmanaged { get { return Mixin.GetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.ManagedMask, (ushort)MethodImplAttributes.Unmanaged); } set { impl_attributes = Mixin.SetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.ManagedMask, (ushort)MethodImplAttributes.Unmanaged, value); } } public bool IsManaged { get { return Mixin.GetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.ManagedMask, (ushort)MethodImplAttributes.Managed); } set { impl_attributes = Mixin.SetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.ManagedMask, (ushort)MethodImplAttributes.Managed, value); } } public bool IsForwardRef { get { return Mixin.GetAttributes(impl_attributes, (ushort)MethodImplAttributes.ForwardRef); } set { impl_attributes = Mixin.SetAttributes(impl_attributes,(ushort)MethodImplAttributes.ForwardRef, value); } } public bool IsPreserveSig { get { return Mixin.GetAttributes(impl_attributes, (ushort)MethodImplAttributes.PreserveSig); } set { impl_attributes = Mixin.SetAttributes(impl_attributes,(ushort)MethodImplAttributes.PreserveSig, value); } } public bool IsInternalCall { get { return Mixin.GetAttributes(impl_attributes, (ushort)MethodImplAttributes.InternalCall); } set { impl_attributes = Mixin.SetAttributes(impl_attributes,(ushort)MethodImplAttributes.InternalCall, value); } } public bool IsSynchronized { get { return Mixin.GetAttributes(impl_attributes, (ushort)MethodImplAttributes.Synchronized); } set { impl_attributes = Mixin.SetAttributes(impl_attributes,(ushort)MethodImplAttributes.Synchronized, value); } } public bool NoInlining { get { return Mixin.GetAttributes(impl_attributes, (ushort)MethodImplAttributes.NoInlining); } set { impl_attributes = Mixin.SetAttributes(impl_attributes,(ushort)MethodImplAttributes.NoInlining, value); } } public bool NoOptimization { get { return Mixin.GetAttributes(impl_attributes, (ushort)MethodImplAttributes.NoOptimization); } set { impl_attributes = Mixin.SetAttributes(impl_attributes,(ushort)MethodImplAttributes.NoOptimization, value); } } #endregion #region MethodSemanticsAttributes public bool IsSetter { get { return Mixin.GetSemantics(this, MethodSemanticsAttributes.Setter); } set { Mixin.SetSemantics(this, MethodSemanticsAttributes.Setter, value); } } public bool IsGetter { get { return Mixin.GetSemantics(this, MethodSemanticsAttributes.Getter); } set { Mixin.SetSemantics(this, MethodSemanticsAttributes.Getter, value); } } public bool IsOther { get { return Mixin.GetSemantics(this, MethodSemanticsAttributes.Other); } set { Mixin.SetSemantics(this, MethodSemanticsAttributes.Other, value); } } public bool IsAddOn { get { return Mixin.GetSemantics(this, MethodSemanticsAttributes.AddOn); } set { Mixin.SetSemantics(this, MethodSemanticsAttributes.AddOn, value); } } public bool IsRemoveOn { get { return Mixin.GetSemantics(this, MethodSemanticsAttributes.RemoveOn); } set { Mixin.SetSemantics(this, MethodSemanticsAttributes.RemoveOn, value); } } public bool IsFire { get { return Mixin.GetSemantics(this, MethodSemanticsAttributes.Fire); } set { Mixin.SetSemantics(this, MethodSemanticsAttributes.Fire, value); } } #endregion public new TypeDefinition DeclaringType { get { return (TypeDefinition)base.DeclaringType; } set { base.DeclaringType = value; } } public bool IsConstructor { get { return this.IsRuntimeSpecialName && this.IsSpecialName && (this.Name == ".cctor" || this.Name == ".ctor"); } } public override bool IsDefinition { get { return true; } } internal MethodDefinition() { this.token = new MetadataToken(TokenType.Method); } public MethodDefinition(string name, MethodAttributes attributes, TypeReference returnType) : base(name, returnType) { this.attributes = (ushort)attributes; this.HasThis = !this.IsStatic; this.token = new MetadataToken(TokenType.Method); } public override MethodDefinition Resolve() { return this; } } static partial class Mixin { public static ParameterDefinition GetParameter(MethodBody self, int index) { var method = self.method; if (method.HasThis) { if (index == 0) return self.ThisParameter; index--; } var parameters = method.Parameters; if (index < 0 || index >= parameters.size) return null; return parameters[index]; } public static VariableDefinition GetVariable(MethodBody self, int index) { var variables = self.Variables; if (index < 0 || index >= variables.size) return null; return variables[index]; } public static bool GetSemantics(MethodDefinition self, MethodSemanticsAttributes semantics) { return (self.SemanticsAttributes & semantics) != 0; } public static void SetSemantics(MethodDefinition self, MethodSemanticsAttributes semantics, bool value) { if (value) self.SemanticsAttributes |= semantics; else self.SemanticsAttributes &= ~semantics; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/MethodImplAttributes.cs ================================================ // // MethodImplAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum MethodImplAttributes : ushort { CodeTypeMask = 0x0003, IL = 0x0000, // Method impl is CIL Native = 0x0001, // Method impl is native OPTIL = 0x0002, // Reserved: shall be zero in conforming implementations Runtime = 0x0003, // Method impl is provided by the runtime ManagedMask = 0x0004, // Flags specifying whether the code is managed or unmanaged Unmanaged = 0x0004, // Method impl is unmanaged, otherwise managed Managed = 0x0000, // Method impl is managed // Implementation info and interop ForwardRef = 0x0010, // Indicates method is defined; used primarily in merge scenarios PreserveSig = 0x0080, // Reserved: conforming implementations may ignore InternalCall = 0x1000, // Reserved: shall be zero in conforming implementations Synchronized = 0x0020, // Method is single threaded through the body NoOptimization = 0x0040, // Method is not optimized by the JIT. NoInlining = 0x0008, // Method may not be inlined } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/MethodReference.cs ================================================ // // MethodReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Text; using Mono.Collections.Generic; namespace Mono.Cecil { public class MethodReference : MemberReference, IMethodSignature, IGenericParameterProvider, IGenericContext { int hashCode = -1; static int instance_id; internal ParameterDefinitionCollection parameters; MethodReturnType return_type; bool has_this; bool explicit_this; MethodCallingConvention calling_convention; internal Collection generic_parameters; public virtual bool HasThis { get { return has_this; } set { has_this = value; } } public virtual bool ExplicitThis { get { return explicit_this; } set { explicit_this = value; } } public virtual MethodCallingConvention CallingConvention { get { return calling_convention; } set { calling_convention = value; } } public virtual bool HasParameters { get { return !Mixin.IsNullOrEmpty(parameters); } } public virtual Collection Parameters { get { if (parameters == null) parameters = new ParameterDefinitionCollection(this); return parameters; } } IGenericParameterProvider IGenericContext.Type { get { var declaring_type = this.DeclaringType; var instance = declaring_type as GenericInstanceType; if (instance != null) return instance.ElementType; return declaring_type; } } IGenericParameterProvider IGenericContext.Method { get { return this; } } GenericParameterType IGenericParameterProvider.GenericParameterType { get { return GenericParameterType.Method; } } public virtual bool HasGenericParameters { get { return !Mixin.IsNullOrEmpty(generic_parameters); } } public virtual Collection GenericParameters { get { if (generic_parameters != null) return generic_parameters; return generic_parameters = new GenericParameterCollection(this); } } public TypeReference ReturnType { get { var return_type = MethodReturnType; return return_type != null ? return_type.ReturnType : null; } set { var return_type = MethodReturnType; if (return_type != null) return_type.ReturnType = value; } } public virtual MethodReturnType MethodReturnType { get { return return_type; } set { return_type = value; } } public override string FullName { get { var builder = new StringBuilder(); builder.Append(ReturnType.FullName) .Append(" ") .Append(MemberFullName()); Mixin.MethodSignatureFullName(this, builder); return builder.ToString(); } } public override int GetHashCode() { if (hashCode == -1) hashCode = System.Threading.Interlocked.Add(ref instance_id, 1); return hashCode; } public virtual bool IsGenericInstance { get { return false; } } internal override bool ContainsGenericParameter { get { if (this.ReturnType.ContainsGenericParameter || base.ContainsGenericParameter) return true; var parameters = this.Parameters; for (int i = 0; i < parameters.Count; i++) if (parameters[i].ParameterType.ContainsGenericParameter) return true; return false; } } internal MethodReference() { this.return_type = new MethodReturnType(this); this.token = new MetadataToken(TokenType.MemberRef); } public MethodReference(string name, TypeReference returnType) : base(name) { if (returnType == null) throw new ArgumentNullException("returnType"); this.return_type = new MethodReturnType(this); this.return_type.ReturnType = returnType; this.token = new MetadataToken(TokenType.MemberRef); } public MethodReference(string name, TypeReference returnType, TypeReference declaringType) : this(name, returnType) { if (declaringType == null) throw new ArgumentNullException("declaringType"); this.DeclaringType = declaringType; } public virtual MethodReference GetElementMethod() { return this; } public virtual MethodDefinition Resolve() { var module = this.Module; if (module == null) throw new NotSupportedException(); return module.Resolve(this); } } static partial class Mixin { public static bool IsVarArg(IMethodSignature self) { return (self.CallingConvention & MethodCallingConvention.VarArg) != 0; } public static int GetSentinelPosition(IMethodSignature self) { if (!self.HasParameters) return -1; var parameters = self.Parameters; for (int i = 0; i < parameters.Count; i++) if (parameters[i].ParameterType.IsSentinel) return i; return -1; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/MethodReturnType.cs ================================================ // // MethodReturnType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System.Threading; using Mono.Collections.Generic; namespace Mono.Cecil { public sealed class MethodReturnType : IConstantProvider, ICustomAttributeProvider, IMarshalInfoProvider { internal IMethodSignature method; internal ParameterDefinition parameter; TypeReference return_type; public IMethodSignature Method { get { return method; } } public TypeReference ReturnType { get { return return_type; } set { return_type = value; } } internal ParameterDefinition Parameter { get { if (parameter == null) parameter=new ParameterDefinition (return_type, method); return parameter; } } public MetadataToken MetadataToken { get { return Parameter.MetadataToken; } set { Parameter.MetadataToken = value; } } public ParameterAttributes Attributes { get { return Parameter.Attributes; } set { Parameter.Attributes = value; } } public bool HasCustomAttributes { get { return parameter != null && parameter.HasCustomAttributes; } } public Collection CustomAttributes { get { return Parameter.CustomAttributes; } } public bool HasDefault { get { return parameter != null && parameter.HasDefault; } set { Parameter.HasDefault = value; } } public bool HasConstant { get { return parameter != null && parameter.HasConstant; } set { Parameter.HasConstant = value; } } public object Constant { get { return Parameter.Constant; } set { Parameter.Constant = value; } } public bool HasFieldMarshal { get { return parameter != null && parameter.HasFieldMarshal; } set { Parameter.HasFieldMarshal = value; } } public bool HasMarshalInfo { get { return parameter != null && parameter.HasMarshalInfo; } } public MarshalInfo MarshalInfo { get { return Parameter.MarshalInfo; } set { Parameter.MarshalInfo = value; } } public MethodReturnType (IMethodSignature method) { this.method = method; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/MethodSemanticsAttributes.cs ================================================ // // MethodSemanticsattributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum MethodSemanticsAttributes : ushort { None = 0x0000, Setter = 0x0001, // Setter for property Getter = 0x0002, // Getter for property Other = 0x0004, // Other method for property or event AddOn = 0x0008, // AddOn method for event RemoveOn = 0x0010, // RemoveOn method for event Fire = 0x0020 // Fire method for event } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/MethodSpecification.cs ================================================ // // MethodSpecification.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Collections.Generic; namespace Mono.Cecil { public abstract class MethodSpecification : MethodReference { readonly MethodReference method; public MethodReference ElementMethod { get { return method; } } public override string Name { get { return method.Name; } set { throw new InvalidOperationException (); } } public override MethodCallingConvention CallingConvention { get { return method.CallingConvention; } set { throw new InvalidOperationException (); } } public override bool HasThis { get { return method.HasThis; } set { throw new InvalidOperationException (); } } public override bool ExplicitThis { get { return method.ExplicitThis; } set { throw new InvalidOperationException (); } } public override MethodReturnType MethodReturnType { get { return method.MethodReturnType; } set { throw new InvalidOperationException (); } } public override TypeReference DeclaringType { get { return method.DeclaringType; } set { throw new InvalidOperationException (); } } public override ModuleDefinition Module { get { return method.Module; } } public override bool HasParameters { get { return method.HasParameters; } } public override Collection Parameters { get { return method.Parameters; } } internal override bool ContainsGenericParameter { get { return method.ContainsGenericParameter; } } internal MethodSpecification (MethodReference method) { if (method == null) throw new ArgumentNullException ("method"); this.method = method; this.token = new MetadataToken (TokenType.MethodSpec); } public sealed override MethodReference GetElementMethod () { return method.GetElementMethod (); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/Modifiers.cs ================================================ // // Modifiers.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using MD = Mono.Cecil.Metadata; namespace Mono.Cecil { public interface IModifierType { TypeReference ModifierType { get; } TypeReference ElementType { get; } } public sealed class OptionalModifierType : TypeSpecification, IModifierType { TypeReference modifier_type; public TypeReference ModifierType { get { return modifier_type; } set { modifier_type = value; } } public override string Name { get { return base.Name + Suffix; } } public override string FullName { get { return base.FullName + Suffix; } } string Suffix { get { return " modopt(" + modifier_type + ")"; } } public override bool IsValueType { get { return false; } set { throw new InvalidOperationException (); } } public override bool IsOptionalModifier { get { return true; } } internal override bool ContainsGenericParameter { get { return modifier_type.ContainsGenericParameter || base.ContainsGenericParameter; } } public OptionalModifierType (TypeReference modifierType, TypeReference type) : base (type) { Mixin.CheckModifier (modifierType, type); this.modifier_type = modifierType; this.etype = MD.ElementType.CModOpt; } } public sealed class RequiredModifierType : TypeSpecification, IModifierType { TypeReference modifier_type; public TypeReference ModifierType { get { return modifier_type; } set { modifier_type = value; } } public override string Name { get { return base.Name + Suffix; } } public override string FullName { get { return base.FullName + Suffix; } } string Suffix { get { return " modreq(" + modifier_type + ")"; } } public override bool IsValueType { get { return false; } set { throw new InvalidOperationException (); } } public override bool IsRequiredModifier { get { return true; } } internal override bool ContainsGenericParameter { get { return modifier_type.ContainsGenericParameter || base.ContainsGenericParameter; } } public RequiredModifierType (TypeReference modifierType, TypeReference type) : base (type) { Mixin.CheckModifier (modifierType, type); this.modifier_type = modifierType; this.etype = MD.ElementType.CModReqD; } } static partial class Mixin { public static void CheckModifier (TypeReference modifierType, TypeReference type) { if (modifierType == null) throw new ArgumentNullException ("modifierType"); if (type == null) throw new ArgumentNullException ("type"); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/ModuleDefinition.cs ================================================ // // ModuleDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using System.IO; using System.Threading; using SR = System.Reflection; using Mono.Cecil.Cil; using Mono.Cecil.Metadata; using Mono.Cecil.PE; using Mono.Collections.Generic; namespace Mono.Cecil { public enum ReadingMode { Immediate = 1, Deferred = 2, } public sealed class ReaderParameters { ReadingMode reading_mode; IAssemblyResolver assembly_resolver; IMetadataResolver metadata_resolver; Stream symbol_stream; ISymbolReaderProvider symbol_reader_provider; bool read_symbols; public ReadingMode ReadingMode { get { return reading_mode; } set { reading_mode = value; } } public IAssemblyResolver AssemblyResolver { get { return assembly_resolver; } set { assembly_resolver = value; } } public IMetadataResolver MetadataResolver { get { return metadata_resolver; } set { metadata_resolver = value; } } public Stream SymbolStream { get { return symbol_stream; } set { symbol_stream = value; } } public ISymbolReaderProvider SymbolReaderProvider { get { return symbol_reader_provider; } set { symbol_reader_provider = value; } } public bool ReadSymbols { get { return read_symbols; } set { read_symbols = value; } } public ReaderParameters() : this(ReadingMode.Deferred) { } public ReaderParameters(ReadingMode readingMode) { this.reading_mode = readingMode; } } public sealed class ModuleDefinition : ModuleReference, ICustomAttributeProvider { internal Image Image; internal MetadataSystem MetadataSystem; internal ReadingMode ReadingMode; internal ISymbolReaderProvider SymbolReaderProvider; internal ISymbolReader symbol_reader; internal IAssemblyResolver assembly_resolver; internal IMetadataResolver metadata_resolver; internal TypeSystem type_system; readonly MetadataReader reader; readonly string fq_name; internal ModuleKind kind; TargetRuntime runtime; TargetArchitecture architecture; ModuleAttributes attributes; ModuleCharacteristics characteristics; Guid mvid; internal AssemblyDefinition assembly; MethodDefinition entry_point; Collection custom_attributes; Collection references; Collection modules; Collection resources; Collection exported_types; TypeDefinitionCollection types; public bool IsMain { get { return kind != ModuleKind.NetModule; } } public ModuleKind Kind { get { return kind; } set { kind = value; } } public TargetRuntime Runtime { get { return runtime; } set { runtime = value; } } public TargetArchitecture Architecture { get { return architecture; } set { architecture = value; } } public ModuleAttributes Attributes { get { return attributes; } set { attributes = value; } } public ModuleCharacteristics Characteristics { get { return characteristics; } set { characteristics = value; } } public string FullyQualifiedName { get { return fq_name; } } public Guid Mvid { get { return mvid; } set { mvid = value; } } internal bool HasImage { get { return Image != null; } } public bool HasSymbols { get { return symbol_reader != null; } } public ISymbolReader SymbolReader { get { return symbol_reader; } } public override MetadataScopeType MetadataScopeType { get { return MetadataScopeType.ModuleDefinition; } } public AssemblyDefinition Assembly { get { return assembly; } } public IAssemblyResolver AssemblyResolver { get { return assembly_resolver ?? (assembly_resolver = new DefaultAssemblyResolver()); } } public IMetadataResolver MetadataResolver { get { if (metadata_resolver == null) metadata_resolver=new MetadataResolver(this.AssemblyResolver); return metadata_resolver; } } public TypeSystem TypeSystem { get { if (type_system == null) type_system = TypeSystem.CreateTypeSystem(this); return type_system; } } public bool HasAssemblyReferences { get { if (references != null) return references.Count > 0; return HasImage && Image.HasTable(Table.AssemblyRef); } } public Collection AssemblyReferences { get { if (references != null) return references; if (HasImage) return Read(ref references, this, (_, reader) => reader.ReadAssemblyReferences()); return references = new Collection(); } } public bool HasModuleReferences { get { if (modules != null) return modules.Count > 0; return HasImage && Image.HasTable(Table.ModuleRef); } } public Collection ModuleReferences { get { if (modules != null) return modules; if (HasImage) return Read(ref modules, this, (_, reader) => reader.ReadModuleReferences()); return modules = new Collection(); } } public bool HasResources { get { if (resources != null) return resources.Count > 0; if (HasImage) return Image.HasTable(Table.ManifestResource) || Read(this, (_, reader) => reader.HasFileResource()); return false; } } public Collection Resources { get { if (resources != null) return resources; if (HasImage) return Read(ref resources, this, (_, reader) => reader.ReadResources()); return resources = new Collection(); } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return Mixin.GetHasCustomAttributes(this, this); } } public Collection CustomAttributes { get { return custom_attributes ?? (Mixin.GetCustomAttributes(this, ref custom_attributes, this)); } } public bool HasTypes { get { if (types != null) return types.Count > 0; return HasImage && Image.HasTable(Table.TypeDef); } } public Collection Types { get { if (types != null) return types; if (HasImage) return Read(ref types, this, (_, reader) => reader.ReadTypes()); return types = new TypeDefinitionCollection(this); } } public bool HasExportedTypes { get { if (exported_types != null) return exported_types.Count > 0; return HasImage && Image.HasTable(Table.ExportedType); } } public Collection ExportedTypes { get { if (exported_types != null) return exported_types; if (HasImage) return Read(ref exported_types, this, (_, reader) => reader.ReadExportedTypes()); return exported_types = new Collection(); } } public MethodDefinition EntryPoint { get { if (entry_point != null) return entry_point; if (HasImage) return Read(ref entry_point, this, (_, reader) => reader.ReadEntryPoint()); return entry_point = null; } set { entry_point = value; } } internal ModuleDefinition() { this.MetadataSystem = new MetadataSystem(); this.token = new MetadataToken(TokenType.Module, 1); } internal ModuleDefinition(Image image) : this() { this.Image = image; this.kind = image.Kind; this.runtime = image.Runtime; this.architecture = image.Architecture; this.attributes = image.Attributes; this.characteristics = image.Characteristics; this.fq_name = image.FileName; this.reader = new MetadataReader(this); } public bool HasTypeReference(string fullName) { return HasTypeReference(string.Empty, fullName); } public bool HasTypeReference(string scope, string fullName) { CheckFullName(fullName); if (!HasImage) return false; return GetTypeReference(scope, fullName) != null; } public bool TryGetTypeReference(string fullName, out TypeReference type) { return TryGetTypeReference(string.Empty, fullName, out type); } public bool TryGetTypeReference(string scope, string fullName, out TypeReference type) { CheckFullName(fullName); if (!HasImage) { type = null; return false; } return (type = GetTypeReference(scope, fullName)) != null; } TypeReference GetTypeReference(string scope, string fullname) { return Read(new Row(scope, fullname), (row, reader) => reader.GetTypeReference(row.Col1, row.Col2)); } public IEnumerable GetTypeReferences() { if (!HasImage) return Empty.Array; return Read(this, (_, reader) => reader.GetTypeReferences()); } public IEnumerable GetMemberReferences() { if (!HasImage) return Empty.Array; return Read(this, (_, reader) => reader.GetMemberReferences()); } public TypeReference GetType(string fullName, bool runtimeName) { return runtimeName ? TypeParser.ParseType(this, fullName) : GetType(fullName); } public TypeDefinition GetType(string fullName) { CheckFullName(fullName); var position = fullName.IndexOf('/'); if (position > 0) return GetNestedType(fullName); return ((TypeDefinitionCollection)this.Types).GetType(fullName); } public TypeDefinition GetType(string @namespace, string name) { Mixin.CheckName(name); return ((TypeDefinitionCollection)this.Types).GetType(@namespace ?? string.Empty, name); } public IEnumerable GetTypes() { return GetTypes(Types); } static IEnumerable GetTypes(Collection types) { for (int i = 0; i < types.Count; i++) { var type = types[i]; yield return type; if (!type.HasNestedTypes) continue; foreach (var nested in GetTypes(type.NestedTypes)) yield return nested; } } static void CheckFullName(string fullName) { if (fullName == null) throw new ArgumentNullException("fullName"); if (fullName.Length == 0) throw new ArgumentException(); } TypeDefinition GetNestedType(string fullname) { var names = fullname.Split('/'); var type = GetType(names[0]); if (type == null) return null; for (int i = 1; i < names.Length; i++) { var nested_type = Mixin.GetNestedType(type, names[i]); if (nested_type == null) return null; type = nested_type; } return type; } internal FieldDefinition Resolve(FieldReference field) { return MetadataResolver.Resolve(field); } internal MethodDefinition Resolve(MethodReference method) { return MetadataResolver.Resolve(method); } internal TypeDefinition Resolve(TypeReference type) { return MetadataResolver.Resolve(type); } public IMetadataTokenProvider LookupToken(int token) { return LookupToken(new MetadataToken((uint)token)); } public IMetadataTokenProvider LookupToken(MetadataToken token) { return Read(token, (t, reader) => reader.LookupToken(t)); } readonly object module_lock = new object(); internal object SyncRoot { get { return module_lock; } } internal TRet Read(TItem item, Func read) { lock (module_lock) { var position = reader.position; var context = reader.context; var ret = read(item, reader); reader.position = position; reader.context = context; return ret; } } internal TRet Read(ref TRet variable, TItem item, Func read) where TRet : class { lock (module_lock) { if (variable != null) return variable; var position = reader.position; var context = reader.context; var ret = read(item, reader); reader.position = position; reader.context = context; return variable = ret; } } public bool HasDebugHeader { get { return Image != null && !Image.Debug.IsZero; } } public ImageDebugDirectory GetDebugHeader(out byte[] header) { if (!HasDebugHeader) throw new InvalidOperationException(); return Image.GetDebugHeader(out header); } void ProcessDebugHeader() { if (!HasDebugHeader) return; byte[] header; var directory = GetDebugHeader(out header); if (!symbol_reader.ProcessDebugHeader(directory, header)) throw new InvalidOperationException(); } public void ReadSymbols() { if (string.IsNullOrEmpty(fq_name)) throw new InvalidOperationException(); var provider = SymbolProvider.GetPlatformReaderProvider(); if (provider == null) throw new InvalidOperationException(); ReadSymbols(provider.GetSymbolReader(this, fq_name)); } public void ReadSymbols(ISymbolReader reader) { if (reader == null) throw new ArgumentNullException("reader"); symbol_reader = reader; ProcessDebugHeader(); } public static ModuleDefinition ReadModule(string fileName) { return ReadModule(fileName, new ReaderParameters(ReadingMode.Deferred)); } public static ModuleDefinition ReadModule(Stream stream) { return ReadModule(stream, new ReaderParameters(ReadingMode.Deferred)); } public static ModuleDefinition ReadModule(string fileName, ReaderParameters parameters) { using (var stream = GetFileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { return ReadModule(stream, parameters); } } static void CheckStream(object stream) { if (stream == null) throw new ArgumentNullException("stream"); } public static ModuleDefinition ReadModule(Stream stream, ReaderParameters parameters) { CheckStream(stream); if (!stream.CanRead || !stream.CanSeek) throw new ArgumentException(); Mixin.CheckParameters(parameters); return ModuleReader.CreateModuleFrom( ImageReader.ReadImageFrom(stream), parameters); } static Stream GetFileStream(string fileName, FileMode mode, FileAccess access, FileShare share) { if (fileName == null) throw new ArgumentNullException("fileName"); if (fileName.Length == 0) throw new ArgumentException(); return new FileStream(fileName, mode, access, share); } } static partial class Mixin { public static void CheckParameters(object parameters) { if (parameters == null) throw new ArgumentNullException("parameters"); } public static bool HasImage(ModuleDefinition self) { return self != null && self.HasImage; } public static bool IsCorlib(ModuleDefinition module) { if (module.Assembly == null) return false; return module.Assembly.Name.Name == "mscorlib"; } public static string GetFullyQualifiedName(Stream self) { return string.Empty; } public static TargetRuntime ParseRuntime(string self) { switch (self[1]) { case '1': return self[3] == '0' ? TargetRuntime.Net_1_0 : TargetRuntime.Net_1_1; case '2': return TargetRuntime.Net_2_0; case '4': default: return TargetRuntime.Net_4_0; } } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/ModuleKind.cs ================================================ // // ModuleKind.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { public enum ModuleKind { Dll, Console, Windows, NetModule, } public enum TargetArchitecture { I386, AMD64, IA64, ARMv7, } [Flags] public enum ModuleAttributes { ILOnly = 1, Required32Bit = 2, StrongNameSigned = 8, Preferred32Bit = 0x00020000, } [Flags] public enum ModuleCharacteristics { HighEntropyVA = 0x0020, DynamicBase = 0x0040, NoSEH = 0x0400, NXCompat = 0x0100, AppContainer = 0x1000, TerminalServerAware = 0x8000, } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/ModuleReference.cs ================================================ // // ModuleReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public class ModuleReference : IMetadataScope { string name; internal MetadataToken token; public string Name { get { return name; } set { name = value; } } public virtual MetadataScopeType MetadataScopeType { get { return MetadataScopeType.ModuleReference; } } public MetadataToken MetadataToken { get { return token; } set { token = value; } } internal ModuleReference () { this.token = new MetadataToken (TokenType.ModuleRef); } public ModuleReference (string name) : this () { this.name = name; } public override string ToString () { return name; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/NativeType.cs ================================================ // // NativeType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public enum NativeType { None = 0x66, Boolean = 0x02, I1 = 0x03, U1 = 0x04, I2 = 0x05, U2 = 0x06, I4 = 0x07, U4 = 0x08, I8 = 0x09, U8 = 0x0a, R4 = 0x0b, R8 = 0x0c, LPStr = 0x14, Int = 0x1f, UInt = 0x20, Func = 0x26, Array = 0x2a, // Msft specific Currency = 0x0f, BStr = 0x13, LPWStr = 0x15, LPTStr = 0x16, FixedSysString = 0x17, IUnknown = 0x19, IDispatch = 0x1a, Struct = 0x1b, IntF = 0x1c, SafeArray = 0x1d, FixedArray = 0x1e, ByValStr = 0x22, ANSIBStr = 0x23, TBStr = 0x24, VariantBool = 0x25, ASAny = 0x28, LPStruct = 0x2b, CustomMarshaler = 0x2c, Error = 0x2d, Max = 0x50 } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/PInvokeAttributes.cs ================================================ // // PInvokeAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum PInvokeAttributes : ushort { NoMangle = 0x0001, // PInvoke is to use the member name as specified // Character set CharSetMask = 0x0006, CharSetNotSpec = 0x0000, CharSetAnsi = 0x0002, CharSetUnicode = 0x0004, CharSetAuto = 0x0006, SupportsLastError = 0x0040, // Information about target function. Not relevant for fields // Calling convetion CallConvMask = 0x0700, CallConvWinapi = 0x0100, CallConvCdecl = 0x0200, CallConvStdCall = 0x0300, CallConvThiscall = 0x0400, CallConvFastcall = 0x0500, BestFitMask = 0x0030, BestFitEnabled = 0x0010, BestFitDisabled = 0x0020, ThrowOnUnmappableCharMask = 0x3000, ThrowOnUnmappableCharEnabled = 0x1000, ThrowOnUnmappableCharDisabled = 0x2000, } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/PInvokeInfo.cs ================================================ // // PInvokeInfo.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public sealed class PInvokeInfo { ushort attributes; string entry_point; ModuleReference module; public PInvokeAttributes Attributes { get { return (PInvokeAttributes) attributes; } set { attributes = (ushort) value; } } public string EntryPoint { get { return entry_point; } set { entry_point = value; } } public ModuleReference Module { get { return module; } set { module = value; } } #region PInvokeAttributes public bool IsNoMangle { get { return Mixin.GetAttributes(attributes,(ushort) PInvokeAttributes.NoMangle); } set { attributes =Mixin.SetAttributes(attributes,(ushort) PInvokeAttributes.NoMangle, value); } } public bool IsCharSetNotSpec { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetNotSpec); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetNotSpec, value); } } public bool IsCharSetAnsi { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetAnsi); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetAnsi, value); } } public bool IsCharSetUnicode { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetUnicode); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetUnicode, value); } } public bool IsCharSetAuto { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetAuto); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetAuto, value); } } public bool SupportsLastError { get { return Mixin.GetAttributes(attributes,(ushort) PInvokeAttributes.SupportsLastError); } set { attributes =Mixin.SetAttributes(attributes,(ushort) PInvokeAttributes.SupportsLastError, value); } } public bool IsCallConvWinapi { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvWinapi); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvWinapi, value); } } public bool IsCallConvCdecl { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvCdecl); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvCdecl, value); } } public bool IsCallConvStdCall { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvStdCall); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvStdCall, value); } } public bool IsCallConvThiscall { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvThiscall); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvThiscall, value); } } public bool IsCallConvFastcall { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvFastcall); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvFastcall, value); } } public bool IsBestFitEnabled { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.BestFitMask, (ushort) PInvokeAttributes.BestFitEnabled); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.BestFitMask, (ushort) PInvokeAttributes.BestFitEnabled, value); } } public bool IsBestFitDisabled { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.BestFitMask, (ushort) PInvokeAttributes.BestFitDisabled); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.BestFitMask, (ushort) PInvokeAttributes.BestFitDisabled, value); } } public bool IsThrowOnUnmappableCharEnabled { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.ThrowOnUnmappableCharMask, (ushort) PInvokeAttributes.ThrowOnUnmappableCharEnabled); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.ThrowOnUnmappableCharMask, (ushort) PInvokeAttributes.ThrowOnUnmappableCharEnabled, value); } } public bool IsThrowOnUnmappableCharDisabled { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.ThrowOnUnmappableCharMask, (ushort) PInvokeAttributes.ThrowOnUnmappableCharDisabled); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.ThrowOnUnmappableCharMask, (ushort) PInvokeAttributes.ThrowOnUnmappableCharDisabled, value); } } #endregion public PInvokeInfo (PInvokeAttributes attributes, string entryPoint, ModuleReference module) { this.attributes = (ushort) attributes; this.entry_point = entryPoint; this.module = module; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/ParameterAttributes.cs ================================================ // // ParameterAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum ParameterAttributes : ushort { None = 0x0000, In = 0x0001, // Param is [In] Out = 0x0002, // Param is [Out] Lcid = 0x0004, Retval = 0x0008, Optional = 0x0010, // Param is optional HasDefault = 0x1000, // Param has default value HasFieldMarshal = 0x2000, // Param has field marshal Unused = 0xcfe0 // Reserved: shall be zero in a conforming implementation } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/ParameterDefinition.cs ================================================ // // ParameterDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using Mono.Collections.Generic; namespace Mono.Cecil { public sealed class ParameterDefinition : ParameterReference, ICustomAttributeProvider, IConstantProvider, IMarshalInfoProvider { ushort attributes; internal IMethodSignature method; object constant = Mixin.NotResolved; Collection custom_attributes; MarshalInfo marshal_info; public ParameterAttributes Attributes { get { return (ParameterAttributes)attributes; } set { attributes = (ushort)value; } } public IMethodSignature Method { get { return method; } } public int Sequence { get { if (method == null) return -1; return Mixin.HasImplicitThis(method) ? index + 1 : index; } } public bool HasConstant { get { Mixin.ResolveConstant(this, ref constant, parameter_type.Module); return constant != Mixin.NoValue; } set { if (!value) constant = Mixin.NoValue; } } public object Constant { get { return HasConstant ? constant : null; } set { constant = value; } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return Mixin.GetHasCustomAttributes(this, parameter_type.Module); } } public Collection CustomAttributes { get { return custom_attributes ?? (Mixin.GetCustomAttributes(this, ref custom_attributes, parameter_type.Module)); } } public bool HasMarshalInfo { get { if (marshal_info != null) return true; return Mixin.GetHasMarshalInfo(this, parameter_type.Module); } } public MarshalInfo MarshalInfo { get { return marshal_info ?? (Mixin.GetMarshalInfo(this, ref marshal_info, parameter_type.Module)); } set { marshal_info = value; } } #region ParameterAttributes public bool IsIn { get { return Mixin.GetAttributes(attributes, (ushort)ParameterAttributes.In); } set { attributes = Mixin.SetAttributes(attributes, (ushort)ParameterAttributes.In, value); } } public bool IsOut { get { return Mixin.GetAttributes(attributes, (ushort)ParameterAttributes.Out); } set { attributes = Mixin.SetAttributes(attributes, (ushort)ParameterAttributes.Out, value); } } public bool IsLcid { get { return Mixin.GetAttributes(attributes, (ushort)ParameterAttributes.Lcid); } set { attributes = Mixin.SetAttributes(attributes, (ushort)ParameterAttributes.Lcid, value); } } public bool IsReturnValue { get { return Mixin.GetAttributes(attributes, (ushort)ParameterAttributes.Retval); } set { attributes = Mixin.SetAttributes(attributes, (ushort)ParameterAttributes.Retval, value); } } public bool IsOptional { get { return Mixin.GetAttributes(attributes, (ushort)ParameterAttributes.Optional); } set { attributes = Mixin.SetAttributes(attributes, (ushort)ParameterAttributes.Optional, value); } } public bool HasDefault { get { return Mixin.GetAttributes(attributes, (ushort)ParameterAttributes.HasDefault); } set { attributes = Mixin.SetAttributes(attributes, (ushort)ParameterAttributes.HasDefault, value); } } public bool HasFieldMarshal { get { return Mixin.GetAttributes(attributes, (ushort)ParameterAttributes.HasFieldMarshal); } set { attributes = Mixin.SetAttributes(attributes, (ushort)ParameterAttributes.HasFieldMarshal, value); } } #endregion internal ParameterDefinition(TypeReference parameterType, IMethodSignature method) : this(string.Empty, ParameterAttributes.None, parameterType) { this.method = method; } public ParameterDefinition(TypeReference parameterType) : this(string.Empty, ParameterAttributes.None, parameterType) { } public ParameterDefinition(string name, ParameterAttributes attributes, TypeReference parameterType) : base(name, parameterType) { this.attributes = (ushort)attributes; this.token = new MetadataToken(TokenType.Param); } public override ParameterDefinition Resolve() { return this; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/ParameterDefinitionCollection.cs ================================================ // // ParameterDefinitionCollection.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Collections.Generic; namespace Mono.Cecil { sealed class ParameterDefinitionCollection : Collection { readonly IMethodSignature method; internal ParameterDefinitionCollection (IMethodSignature method) { this.method = method; } internal ParameterDefinitionCollection (IMethodSignature method, int capacity) : base (capacity) { this.method = method; } protected override void OnAdd (ParameterDefinition item, int index) { item.method = method; item.index = index; } protected override void OnInsert (ParameterDefinition item, int index) { item.method = method; item.index = index; for (int i = index; i < size; i++) items [i].index = i + 1; } protected override void OnSet (ParameterDefinition item, int index) { item.method = method; item.index = index; } protected override void OnRemove (ParameterDefinition item, int index) { item.method = null; item.index = -1; for (int i = index + 1; i < size; i++) items [i].index = i - 1; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/ParameterReference.cs ================================================ // // ParameterReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { public abstract class ParameterReference : IMetadataTokenProvider { string name; internal int index = -1; protected TypeReference parameter_type; internal MetadataToken token; public string Name { get { return name; } set { name = value; } } public int Index { get { return index; } } public TypeReference ParameterType { get { return parameter_type; } set { parameter_type = value; } } public MetadataToken MetadataToken { get { return token; } set { token = value; } } internal ParameterReference (string name, TypeReference parameterType) { if (parameterType == null) throw new ArgumentNullException ("parameterType"); this.name = name ?? string.Empty; this.parameter_type = parameterType; } public override string ToString () { return name; } public abstract ParameterDefinition Resolve (); } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/PinnedType.cs ================================================ // // PinnedType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using MD = Mono.Cecil.Metadata; namespace Mono.Cecil { public sealed class PinnedType : TypeSpecification { public override bool IsValueType { get { return false; } set { throw new InvalidOperationException (); } } public override bool IsPinned { get { return true; } } public PinnedType (TypeReference type) : base (type) { Mixin.CheckType (type); this.etype = MD.ElementType.Pinned; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/PointerType.cs ================================================ // // PointerType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using MD = Mono.Cecil.Metadata; namespace Mono.Cecil { public sealed class PointerType : TypeSpecification { public override string Name { get { return base.Name + "*"; } } public override string FullName { get { return base.FullName + "*"; } } public override bool IsValueType { get { return false; } set { throw new InvalidOperationException (); } } public override bool IsPointer { get { return true; } } public PointerType (TypeReference type) : base (type) { Mixin.CheckType (type); this.etype = MD.ElementType.Ptr; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/PropertyAttributes.cs ================================================ // // PropertyAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum PropertyAttributes : ushort { None = 0x0000, SpecialName = 0x0200, // Property is special RTSpecialName = 0x0400, // Runtime(metadata internal APIs) should check name encoding HasDefault = 0x1000, // Property has default Unused = 0xe9ff // Reserved: shall be zero in a conforming implementation } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/PropertyDefinition.cs ================================================ // // PropertyDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System.Text; using Mono.Collections.Generic; namespace Mono.Cecil { public sealed class PropertyDefinition : PropertyReference, IMemberDefinition, IConstantProvider { bool? has_this; ushort attributes; Collection custom_attributes; internal MethodDefinition get_method; internal MethodDefinition set_method; internal Collection other_methods; object constant = Mixin.NotResolved; public PropertyAttributes Attributes { get { return (PropertyAttributes) attributes; } set { attributes = (ushort) value; } } public bool HasThis { get { if (has_this.HasValue) return has_this.Value; if (GetMethod != null) return get_method.HasThis; if (SetMethod != null) return set_method.HasThis; return false; } set { has_this = value; } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return Mixin.GetHasCustomAttributes(this, Module); } } public Collection CustomAttributes { get { return custom_attributes ?? (Mixin.GetCustomAttributes(this, ref custom_attributes, Module)); } } public MethodDefinition GetMethod { get { if (get_method != null) return get_method; InitializeMethods (); return get_method; } set { get_method = value; } } public MethodDefinition SetMethod { get { if (set_method != null) return set_method; InitializeMethods (); return set_method; } set { set_method = value; } } public bool HasOtherMethods { get { if (other_methods != null) return other_methods.Count > 0; InitializeMethods (); return !Mixin.IsNullOrEmpty (other_methods); } } public Collection OtherMethods { get { if (other_methods != null) return other_methods; InitializeMethods (); if (other_methods != null) return other_methods; return other_methods = new Collection (); } } public bool HasParameters { get { InitializeMethods (); if (get_method != null) return get_method.HasParameters; if (set_method != null) return set_method.HasParameters && set_method.Parameters.Count > 1; return false; } } public override Collection Parameters { get { InitializeMethods (); if (get_method != null) return MirrorParameters (get_method, 0); if (set_method != null) return MirrorParameters (set_method, 1); return new Collection (); } } static Collection MirrorParameters (MethodDefinition method, int bound) { var parameters = new Collection (); if (!method.HasParameters) return parameters; var original_parameters = method.Parameters; var end = original_parameters.Count - bound; for (int i = 0; i < end; i++) parameters.Add (original_parameters [i]); return parameters; } public bool HasConstant { get { Mixin.ResolveConstant(this, ref constant, Module); return constant != Mixin.NoValue; } set { if (!value) constant = Mixin.NoValue; } } public object Constant { get { return HasConstant ? constant : null; } set { constant = value; } } #region PropertyAttributes public bool IsSpecialName { get { return Mixin.GetAttributes(attributes,(ushort) PropertyAttributes.SpecialName); } set { attributes =Mixin.SetAttributes(attributes,(ushort) PropertyAttributes.SpecialName, value); } } public bool IsRuntimeSpecialName { get { return Mixin.GetAttributes(attributes,(ushort) PropertyAttributes.RTSpecialName); } set { attributes =Mixin.SetAttributes(attributes,(ushort) PropertyAttributes.RTSpecialName, value); } } public bool HasDefault { get { return Mixin.GetAttributes(attributes,(ushort) PropertyAttributes.HasDefault); } set { attributes =Mixin.SetAttributes(attributes,(ushort) PropertyAttributes.HasDefault, value); } } #endregion public new TypeDefinition DeclaringType { get { return (TypeDefinition) base.DeclaringType; } set { base.DeclaringType = value; } } public override bool IsDefinition { get { return true; } } public override string FullName { get { var builder = new StringBuilder (); builder.Append (PropertyType.ToString ()); builder.Append (' '); builder.Append (MemberFullName ()); builder.Append ('('); if (HasParameters) { var parameters = Parameters; for (int i = 0; i < parameters.Count; i++) { if (i > 0) builder.Append (','); builder.Append (parameters [i].ParameterType.FullName); } } builder.Append (')'); return builder.ToString (); } } public PropertyDefinition (string name, PropertyAttributes attributes, TypeReference propertyType) : base (name, propertyType) { this.attributes = (ushort) attributes; this.token = new MetadataToken (TokenType.Property); } void InitializeMethods () { var module = this.Module; lock (module.SyncRoot) { if (get_method != null || set_method != null) return; if (!Mixin.HasImage(module)) return; module.Read (this, (property, reader) => reader.ReadMethods (property)); } } public override PropertyDefinition Resolve () { return this; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/PropertyReference.cs ================================================ // // PropertyReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Collections.Generic; namespace Mono.Cecil { public abstract class PropertyReference : MemberReference { TypeReference property_type; public TypeReference PropertyType { get { return property_type; } set { property_type = value; } } public abstract Collection Parameters { get; } internal PropertyReference (string name, TypeReference propertyType) : base (name) { if (propertyType == null) throw new ArgumentNullException ("propertyType"); property_type = propertyType; } public abstract PropertyDefinition Resolve (); } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/ReferenceType.cs ================================================ // // ByReferenceType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using MD = Mono.Cecil.Metadata; namespace Mono.Cecil { public sealed class ByReferenceType : TypeSpecification { public override string Name { get { return base.Name + "&"; } } public override string FullName { get { return base.FullName + "&"; } } public override bool IsValueType { get { return false; } set { throw new InvalidOperationException (); } } public override bool IsByReference { get { return true; } } public ByReferenceType (TypeReference type) : base (type) { Mixin.CheckType (type); this.etype = MD.ElementType.ByRef; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/Resource.cs ================================================ // // ResourceType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public enum ResourceType { Linked, Embedded, AssemblyLinked, } public abstract class Resource { string name; uint attributes; public string Name { get { return name; } set { name = value; } } public ManifestResourceAttributes Attributes { get { return (ManifestResourceAttributes) attributes; } set { attributes = (uint) value; } } public abstract ResourceType ResourceType { get; } #region ManifestResourceAttributes public bool IsPublic { get { return Mixin.GetMaskedAttributes(attributes,(uint) ManifestResourceAttributes.VisibilityMask, (uint) ManifestResourceAttributes.Public); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) ManifestResourceAttributes.VisibilityMask, (uint) ManifestResourceAttributes.Public, value); } } public bool IsPrivate { get { return Mixin.GetMaskedAttributes(attributes,(uint) ManifestResourceAttributes.VisibilityMask, (uint) ManifestResourceAttributes.Private); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) ManifestResourceAttributes.VisibilityMask, (uint) ManifestResourceAttributes.Private, value); } } #endregion internal Resource (string name, ManifestResourceAttributes attributes) { this.name = name; this.attributes = (uint) attributes; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/SecurityDeclaration.cs ================================================ // // SecurityDeclaration.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Threading; using Mono.Collections.Generic; namespace Mono.Cecil { public enum SecurityAction : ushort { Request = 1, Demand = 2, Assert = 3, Deny = 4, PermitOnly = 5, LinkDemand = 6, InheritDemand = 7, RequestMinimum = 8, RequestOptional = 9, RequestRefuse = 10, PreJitGrant = 11, PreJitDeny = 12, NonCasDemand = 13, NonCasLinkDemand = 14, NonCasInheritance = 15 } public interface ISecurityDeclarationProvider : IMetadataTokenProvider { bool HasSecurityDeclarations { get; } Collection SecurityDeclarations { get; } } public sealed class SecurityAttribute : ICustomAttribute { TypeReference attribute_type; internal Collection fields; internal Collection properties; public TypeReference AttributeType { get { return attribute_type; } set { attribute_type = value; } } public bool HasFields { get { return !Mixin.IsNullOrEmpty(fields); } } public Collection Fields { get { return fields ?? (fields = new Collection()); } } public bool HasProperties { get { return !Mixin.IsNullOrEmpty(properties); } } public Collection Properties { get { return properties ?? (properties = new Collection()); } } public SecurityAttribute(TypeReference attributeType) { this.attribute_type = attributeType; } } public sealed class SecurityDeclaration { readonly internal uint signature; byte[] blob; readonly ModuleDefinition module; internal bool resolved; SecurityAction action; internal Collection security_attributes; public SecurityAction Action { get { return action; } set { action = value; } } public bool HasSecurityAttributes { get { Resolve(); return !Mixin.IsNullOrEmpty(security_attributes); } } public Collection SecurityAttributes { get { Resolve(); return security_attributes ?? (security_attributes = new Collection()); } } internal bool HasImage { get { return module != null && module.HasImage; } } internal SecurityDeclaration(SecurityAction action, uint signature, ModuleDefinition module) { this.action = action; this.signature = signature; this.module = module; } public SecurityDeclaration(SecurityAction action) { this.action = action; this.resolved = true; } public SecurityDeclaration(SecurityAction action, byte[] blob) { this.action = action; this.resolved = false; this.blob = blob; } public byte[] GetBlob() { if (blob != null) return blob; if (!HasImage || signature == 0) throw new NotSupportedException(); return blob = module.Read(this, (declaration, reader) => reader.ReadSecurityDeclarationBlob(declaration.signature)); } void Resolve() { if (resolved || !HasImage) return; module.Read(this, (declaration, reader) => { reader.ReadSecurityDeclarationSignature(declaration); return this; }); resolved = true; } } static partial class Mixin { public static bool GetHasSecurityDeclarations( ISecurityDeclarationProvider self, ModuleDefinition module) { return Mixin.HasImage(module) && module.Read(self, (provider, reader) => reader.HasSecurityDeclarations(provider)); } public static Collection GetSecurityDeclarations( ISecurityDeclarationProvider self, ref Collection variable, ModuleDefinition module) { return Mixin.HasImage(module) ? module.Read(ref variable, self, (provider, reader) => reader.ReadSecurityDeclarations(provider)) : variable = new Collection(); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/SentinelType.cs ================================================ // // SentinelType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using MD = Mono.Cecil.Metadata; namespace Mono.Cecil { public sealed class SentinelType : TypeSpecification { public override bool IsValueType { get { return false; } set { throw new InvalidOperationException (); } } public override bool IsSentinel { get { return true; } } public SentinelType (TypeReference type) : base (type) { Mixin.CheckType (type); this.etype = MD.ElementType.Sentinel; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/TargetRuntime.cs ================================================ // // TargetRuntime.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public enum TargetRuntime { Net_1_0, Net_1_1, Net_2_0, Net_4_0, } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/TypeAttributes.cs ================================================ // // TypeAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum TypeAttributes : uint { // Visibility attributes VisibilityMask = 0x00000007, // Use this mask to retrieve visibility information NotPublic = 0x00000000, // Class has no public scope Public = 0x00000001, // Class has public scope NestedPublic = 0x00000002, // Class is nested with public visibility NestedPrivate = 0x00000003, // Class is nested with private visibility NestedFamily = 0x00000004, // Class is nested with family visibility NestedAssembly = 0x00000005, // Class is nested with assembly visibility NestedFamANDAssem = 0x00000006, // Class is nested with family and assembly visibility NestedFamORAssem = 0x00000007, // Class is nested with family or assembly visibility // Class layout attributes LayoutMask = 0x00000018, // Use this mask to retrieve class layout information AutoLayout = 0x00000000, // Class fields are auto-laid out SequentialLayout = 0x00000008, // Class fields are laid out sequentially ExplicitLayout = 0x00000010, // Layout is supplied explicitly // Class semantics attributes ClassSemanticMask = 0x00000020, // Use this mask to retrieve class semantics information Class = 0x00000000, // Type is a class Interface = 0x00000020, // Type is an interface // Special semantics in addition to class semantics Abstract = 0x00000080, // Class is abstract Sealed = 0x00000100, // Class cannot be extended SpecialName = 0x00000400, // Class name is special // Implementation attributes Import = 0x00001000, // Class/Interface is imported Serializable = 0x00002000, // Class is serializable WindowsRuntime = 0x00004000, // Windows Runtime type // String formatting attributes StringFormatMask = 0x00030000, // Use this mask to retrieve string information for native interop AnsiClass = 0x00000000, // LPSTR is interpreted as ANSI UnicodeClass = 0x00010000, // LPSTR is interpreted as Unicode AutoClass = 0x00020000, // LPSTR is interpreted automatically // Class initialization attributes BeforeFieldInit = 0x00100000, // Initialize the class before first static field access // Additional flags RTSpecialName = 0x00000800, // CLI provides 'special' behavior, depending upon the name of the Type HasSecurity = 0x00040000, // Type has security associate with it Forwarder = 0x00200000, // Exported type is a type forwarder } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/TypeDefinition.cs ================================================ // // TypeDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.Metadata; using Mono.Collections.Generic; namespace Mono.Cecil { public sealed class TypeDefinition : TypeReference, IMemberDefinition, ISecurityDeclarationProvider { uint attributes; TypeReference base_type; internal Range fields_range; internal Range methods_range; short packing_size = Mixin.NotResolvedMarker; int class_size = Mixin.NotResolvedMarker; Collection interfaces; Collection nested_types; Collection methods; Collection fields; Collection events; Collection properties; Collection custom_attributes; Collection security_declarations; public TypeAttributes Attributes { get { return (TypeAttributes)attributes; } set { attributes = (uint)value; } } public TypeReference BaseType { get { return base_type; } set { base_type = value; } } void ResolveLayout() { if (packing_size != Mixin.NotResolvedMarker || class_size != Mixin.NotResolvedMarker) return; if (!HasImage) { packing_size = Mixin.NoDataMarker; class_size = Mixin.NoDataMarker; return; } var row = Module.Read(this, (type, reader) => reader.ReadTypeLayout(type)); packing_size = row.Col1; class_size = row.Col2; } public bool HasLayoutInfo { get { if (packing_size >= 0 || class_size >= 0) return true; ResolveLayout(); return packing_size >= 0 || class_size >= 0; } } public short PackingSize { get { if (packing_size >= 0) return packing_size; ResolveLayout(); return packing_size >= 0 ? packing_size : (short)-1; } set { packing_size = value; } } public int ClassSize { get { if (class_size >= 0) return class_size; ResolveLayout(); return class_size >= 0 ? class_size : -1; } set { class_size = value; } } public bool HasInterfaces { get { if (interfaces != null) return interfaces.Count > 0; if (HasImage) return Module.Read(this, (type, reader) => reader.HasInterfaces(type)); return false; } } public Collection Interfaces { get { if (interfaces != null) return interfaces; if (HasImage) return Module.Read(ref interfaces, this, (type, reader) => reader.ReadInterfaces(type)); return interfaces = new Collection(); } } public bool HasNestedTypes { get { if (nested_types != null) return nested_types.Count > 0; if (HasImage) return Module.Read(this, (type, reader) => reader.HasNestedTypes(type)); return false; } } public Collection NestedTypes { get { if (nested_types != null) return nested_types; if (HasImage) return Module.Read(ref nested_types, this, (type, reader) => reader.ReadNestedTypes(type)); return nested_types = new MemberDefinitionCollection(this); } } public bool HasMethods { get { if (methods != null) return methods.Count > 0; if (HasImage) return methods_range.Length > 0; return false; } } public Collection Methods { get { if (methods != null) return methods; if (HasImage) return Module.Read(ref methods, this, (type, reader) => reader.ReadMethods(type)); return methods = new MemberDefinitionCollection(this); } } public bool HasFields { get { if (fields != null) return fields.Count > 0; if (HasImage) return fields_range.Length > 0; return false; } } public Collection Fields { get { if (fields != null) return fields; if (HasImage) return Module.Read(ref fields, this, (type, reader) => reader.ReadFields(type)); return fields = new MemberDefinitionCollection(this); } } public bool HasEvents { get { if (events != null) return events.Count > 0; if (HasImage) return Module.Read(this, (type, reader) => reader.HasEvents(type)); return false; } } public Collection Events { get { if (events != null) return events; if (HasImage) return Module.Read(ref events, this, (type, reader) => reader.ReadEvents(type)); return events = new MemberDefinitionCollection(this); } } public bool HasProperties { get { if (properties != null) return properties.Count > 0; if (HasImage) return Module.Read(this, (type, reader) => reader.HasProperties(type)); return false; } } public Collection Properties { get { if (properties != null) return properties; if (HasImage) return Module.Read(ref properties, this, (type, reader) => reader.ReadProperties(type)); return properties = new MemberDefinitionCollection(this); } } public bool HasSecurityDeclarations { get { if (security_declarations != null) return security_declarations.Count > 0; return Mixin.GetHasSecurityDeclarations(this, Module); } } public Collection SecurityDeclarations { get { return security_declarations ?? (Mixin.GetSecurityDeclarations(this, ref security_declarations, Module)); } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return Mixin.GetHasCustomAttributes(this, Module); } } public Collection CustomAttributes { get { return custom_attributes ?? (Mixin.GetCustomAttributes(this, ref custom_attributes, Module)); } } public override bool HasGenericParameters { get { if (generic_parameters != null) return generic_parameters.Count > 0; return Mixin.GetHasGenericParameters(this, Module); } } public override Collection GenericParameters { get { return generic_parameters ?? (Mixin.GetGenericParameters(this,ref generic_parameters, Module)); } } #region TypeAttributes public bool IsNotPublic { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NotPublic); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NotPublic, value); } } public bool IsPublic { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.Public); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.Public, value); } } public bool IsNestedPublic { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedPublic); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedPublic, value); } } public bool IsNestedPrivate { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedPrivate); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedPrivate, value); } } public bool IsNestedFamily { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamily); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamily, value); } } public bool IsNestedAssembly { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedAssembly); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedAssembly, value); } } public bool IsNestedFamilyAndAssembly { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamANDAssem); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamANDAssem, value); } } public bool IsNestedFamilyOrAssembly { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamORAssem); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamORAssem, value); } } public bool IsAutoLayout { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.AutoLayout); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.AutoLayout, value); } } public bool IsSequentialLayout { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.SequentialLayout); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.SequentialLayout, value); } } public bool IsExplicitLayout { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.ExplicitLayout); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.ExplicitLayout, value); } } public bool IsClass { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.ClassSemanticMask, (uint)TypeAttributes.Class); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.ClassSemanticMask, (uint)TypeAttributes.Class, value); } } public bool IsInterface { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.ClassSemanticMask, (uint)TypeAttributes.Interface); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.ClassSemanticMask, (uint)TypeAttributes.Interface, value); } } public bool IsAbstract { get { return Mixin.GetAttributes(attributes, (uint)TypeAttributes.Abstract); } set { attributes = Mixin.SetAttributes(attributes, (uint)TypeAttributes.Abstract, value); } } public bool IsSealed { get { return Mixin.GetAttributes(attributes, (uint)TypeAttributes.Sealed); } set { attributes = Mixin.SetAttributes(attributes, (uint)TypeAttributes.Sealed, value); } } public bool IsSpecialName { get { return Mixin.GetAttributes(attributes, (uint)TypeAttributes.SpecialName); } set { attributes = Mixin.SetAttributes(attributes, (uint)TypeAttributes.SpecialName, value); } } public bool IsImport { get { return Mixin.GetAttributes(attributes, (uint)TypeAttributes.Import); } set { attributes = Mixin.SetAttributes(attributes, (uint)TypeAttributes.Import, value); } } public bool IsSerializable { get { return Mixin.GetAttributes(attributes, (uint)TypeAttributes.Serializable); } set { attributes = Mixin.SetAttributes(attributes, (uint)TypeAttributes.Serializable, value); } } public bool IsWindowsRuntime { get { return Mixin.GetAttributes(attributes, (uint)TypeAttributes.WindowsRuntime); } set { attributes = Mixin.SetAttributes(attributes, (uint)TypeAttributes.WindowsRuntime, value); } } public bool IsAnsiClass { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.AnsiClass); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.AnsiClass, value); } } public bool IsUnicodeClass { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.UnicodeClass); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.UnicodeClass, value); } } public bool IsAutoClass { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.AutoClass); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.AutoClass, value); } } public bool IsBeforeFieldInit { get { return Mixin.GetAttributes(attributes, (uint)TypeAttributes.BeforeFieldInit); } set { attributes = Mixin.SetAttributes(attributes, (uint)TypeAttributes.BeforeFieldInit, value); } } public bool IsRuntimeSpecialName { get { return Mixin.GetAttributes(attributes, (uint)TypeAttributes.RTSpecialName); } set { attributes = Mixin.SetAttributes(attributes, (uint)TypeAttributes.RTSpecialName, value); } } public bool HasSecurity { get { return Mixin.GetAttributes(attributes, (uint)TypeAttributes.HasSecurity); } set { attributes = Mixin.SetAttributes(attributes, (uint)TypeAttributes.HasSecurity, value); } } #endregion public bool IsEnum { get { return base_type != null && Mixin.IsTypeOf(base_type, "System", "Enum"); } } public override bool IsValueType { get { if (base_type == null) return false; return Mixin.IsTypeOf(base_type, "System", "Enum") || (Mixin.IsTypeOf(base_type, "System", "ValueType") && !Mixin.IsTypeOf(this, "System", "Enum")); } } public override bool IsPrimitive { get { ElementType primitive_etype; return MetadataSystem.TryGetPrimitiveElementType(this, out primitive_etype); } } public override MetadataType MetadataType { get { ElementType primitive_etype; if (MetadataSystem.TryGetPrimitiveElementType(this, out primitive_etype)) return (MetadataType)primitive_etype; return base.MetadataType; } } public override bool IsDefinition { get { return true; } } public new TypeDefinition DeclaringType { get { return (TypeDefinition)base.DeclaringType; } set { base.DeclaringType = value; } } public TypeDefinition(string @namespace, string name, TypeAttributes attributes) : base(@namespace, name) { this.attributes = (uint)attributes; this.token = new MetadataToken(TokenType.TypeDef); } public TypeDefinition(string @namespace, string name, TypeAttributes attributes, TypeReference baseType) : this(@namespace, name, attributes) { this.BaseType = baseType; } public override TypeDefinition Resolve() { return this; } } static partial class Mixin { public static TypeReference GetEnumUnderlyingType(TypeDefinition self) { var fields = self.Fields; for (int i = 0; i < fields.Count; i++) { var field = fields[i]; if (!field.IsStatic) return field.FieldType; } throw new ArgumentException(); } public static TypeDefinition GetNestedType(TypeDefinition self, string name) { if (!self.HasNestedTypes) return null; var nested_types = self.NestedTypes; for (int i = 0; i < nested_types.Count; i++) { var nested_type = nested_types[i]; if (nested_type.Name == name) return nested_type; } return null; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/TypeDefinitionCollection.cs ================================================ // // TypeDefinitionCollection.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using Mono.Cecil.Metadata; using Mono.Collections.Generic; namespace Mono.Cecil { using Slot = Row; sealed class TypeDefinitionCollection : Collection { readonly ModuleDefinition container; readonly Dictionary name_cache; internal TypeDefinitionCollection (ModuleDefinition container) { this.container = container; this.name_cache = new Dictionary (new RowEqualityComparer ()); } internal TypeDefinitionCollection (ModuleDefinition container, int capacity) : base (capacity) { this.container = container; this.name_cache = new Dictionary (capacity, new RowEqualityComparer ()); } protected override void OnAdd (TypeDefinition item, int index) { Attach (item); } protected override void OnSet (TypeDefinition item, int index) { Attach (item); } protected override void OnInsert (TypeDefinition item, int index) { Attach (item); } protected override void OnRemove (TypeDefinition item, int index) { Detach (item); } protected override void OnClear () { foreach (var type in this) Detach (type); } void Attach (TypeDefinition type) { if (type.Module != null && type.Module != container) throw new ArgumentException ("Type already attached"); type.module = container; type.scope = container; name_cache [new Slot (type.Namespace, type.Name)] = type; } void Detach (TypeDefinition type) { type.module = null; type.scope = null; name_cache.Remove (new Slot (type.Namespace, type.Name)); } public TypeDefinition GetType (string fullname) { string @namespace, name; TypeParser.SplitFullName (fullname, out @namespace, out name); return GetType (@namespace, name); } public TypeDefinition GetType (string @namespace, string name) { TypeDefinition type; if (name_cache.TryGetValue (new Slot (@namespace, name), out type)) return type; return null; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/TypeParser.cs ================================================ // // TypeParser.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Text; using Mono.Cecil.Metadata; namespace Mono.Cecil { class TypeParser { class Type { public const int Ptr = -1; public const int ByRef = -2; public const int SzArray = -3; public string type_fullname; public string[] nested_names; public int arity; public int[] specs; public Type[] generic_arguments; public string assembly; } readonly string fullname; readonly int length; int position; TypeParser(string fullname) { this.fullname = fullname; this.length = fullname.Length; } Type ParseType(bool fq_name) { var type = new Type(); type.type_fullname = ParsePart(); type.nested_names = ParseNestedNames(); if (TryGetArity(type)) type.generic_arguments = ParseGenericArguments(type.arity); type.specs = ParseSpecs(); if (fq_name) type.assembly = ParseAssemblyName(); return type; } static bool TryGetArity(Type type) { int arity = 0; TryAddArity(type.type_fullname, ref arity); var nested_names = type.nested_names; if (!Mixin.IsNullOrEmpty(nested_names)) { for (int i = 0; i < nested_names.Length; i++) TryAddArity(nested_names[i], ref arity); } type.arity = arity; return arity > 0; } static bool TryGetArity(string name, out int arity) { arity = 0; var index = name.LastIndexOf('`'); if (index == -1) return false; return ParseInt32(name.Substring(index + 1), out arity); } static bool ParseInt32(string value, out int result) { #if CF try { result = int.Parse (value); return true; } catch { result = 0; return false; } #else return int.TryParse(value, out result); #endif } static void TryAddArity(string name, ref int arity) { int type_arity; if (!TryGetArity(name, out type_arity)) return; arity += type_arity; } string ParsePart() { int start = position; while (position < length && !IsDelimiter(fullname[position])) position++; return fullname.Substring(start, position - start); } static bool IsDelimiter(char chr) { return "+,[]*&".IndexOf(chr) != -1; } void TryParseWhiteSpace() { while (position < length && Char.IsWhiteSpace(fullname[position])) position++; } string[] ParseNestedNames() { string[] nested_names = null; while (TryParse('+')) Add(ref nested_names, ParsePart()); return nested_names; } bool TryParse(char chr) { if (position < length && fullname[position] == chr) { position++; return true; } return false; } static void Add(ref T[] array, T item) { if (array == null) { array = new[] { item }; return; } #if !CF Array.Resize(ref array, array.Length + 1); #else var copy = new T [array.Length + 1]; Array.Copy (array, copy, array.Length); array = copy; #endif array[array.Length - 1] = item; } int[] ParseSpecs() { int[] specs = null; while (position < length) { switch (fullname[position]) { case '*': position++; Add(ref specs, Type.Ptr); break; case '&': position++; Add(ref specs, Type.ByRef); break; case '[': position++; switch (fullname[position]) { case ']': position++; Add(ref specs, Type.SzArray); break; case '*': position++; Add(ref specs, 1); break; default: var rank = 1; while (TryParse(',')) rank++; Add(ref specs, rank); TryParse(']'); break; } break; default: return specs; } } return specs; } Type[] ParseGenericArguments(int arity) { Type[] generic_arguments = null; if (position == length || fullname[position] != '[') return generic_arguments; TryParse('['); for (int i = 0; i < arity; i++) { var fq_argument = TryParse('['); Add(ref generic_arguments, ParseType(fq_argument)); if (fq_argument) TryParse(']'); TryParse(','); TryParseWhiteSpace(); } TryParse(']'); return generic_arguments; } string ParseAssemblyName() { if (!TryParse(',')) return string.Empty; TryParseWhiteSpace(); var start = position; while (position < length) { var chr = fullname[position]; if (chr == '[' || chr == ']') break; position++; } return fullname.Substring(start, position - start); } public static TypeReference ParseType(ModuleDefinition module, string fullname) { if (string.IsNullOrEmpty(fullname)) return null; var parser = new TypeParser(fullname); return GetTypeReference(module, parser.ParseType(true)); } static TypeReference GetTypeReference(ModuleDefinition module, Type type_info) { TypeReference type; if (!TryGetDefinition(module, type_info, out type)) type = CreateReference(type_info, module, GetMetadataScope(module, type_info)); return CreateSpecs(type, type_info); } static TypeReference CreateSpecs(TypeReference type, Type type_info) { type = TryCreateGenericInstanceType(type, type_info); var specs = type_info.specs; if (Mixin.IsNullOrEmpty(specs)) return type; for (int i = 0; i < specs.Length; i++) { switch (specs[i]) { case Type.Ptr: type = new PointerType(type); break; case Type.ByRef: type = new ByReferenceType(type); break; case Type.SzArray: type = new ArrayType(type); break; default: var array = new ArrayType(type); array.Dimensions.Clear(); for (int j = 0; j < specs[i]; j++) array.Dimensions.Add(new ArrayDimension()); type = array; break; } } return type; } static TypeReference TryCreateGenericInstanceType(TypeReference type, Type type_info) { var generic_arguments = type_info.generic_arguments; if (Mixin.IsNullOrEmpty(generic_arguments)) return type; var instance = new GenericInstanceType(type); var instance_arguments = instance.GenericArguments; for (int i = 0; i < generic_arguments.Length; i++) instance_arguments.Add(GetTypeReference(type.Module, generic_arguments[i])); return instance; } public static void SplitFullName(string fullname, out string @namespace, out string name) { var last_dot = fullname.LastIndexOf('.'); if (last_dot == -1) { @namespace = string.Empty; name = fullname; } else { @namespace = fullname.Substring(0, last_dot); name = fullname.Substring(last_dot + 1); } } static TypeReference CreateReference(Type type_info, ModuleDefinition module, IMetadataScope scope) { string @namespace, name; SplitFullName(type_info.type_fullname, out @namespace, out name); var type = new TypeReference(@namespace, name, module, scope); MetadataSystem.TryProcessPrimitiveTypeReference(type); AdjustGenericParameters(type); var nested_names = type_info.nested_names; if (Mixin.IsNullOrEmpty(nested_names)) return type; for (int i = 0; i < nested_names.Length; i++) { type = new TypeReference(string.Empty, nested_names[i], module, null) { DeclaringType = type, }; AdjustGenericParameters(type); } return type; } static void AdjustGenericParameters(TypeReference type) { int arity; if (!TryGetArity(type.Name, out arity)) return; for (int i = 0; i < arity; i++) type.GenericParameters.Add(new GenericParameter(type)); } static IMetadataScope GetMetadataScope(ModuleDefinition module, Type type_info) { if (string.IsNullOrEmpty(type_info.assembly)) return module.TypeSystem.Corlib; return MatchReference(module, AssemblyNameReference.Parse(type_info.assembly)); } static AssemblyNameReference MatchReference(ModuleDefinition module, AssemblyNameReference pattern) { var references = module.AssemblyReferences; for (int i = 0; i < references.Count; i++) { var reference = references[i]; if (reference.FullName == pattern.FullName) return reference; } return pattern; } static bool TryGetDefinition(ModuleDefinition module, Type type_info, out TypeReference type) { type = null; if (!TryCurrentModule(module, type_info)) return false; var typedef = module.GetType(type_info.type_fullname); if (typedef == null) return false; var nested_names = type_info.nested_names; if (!Mixin.IsNullOrEmpty(nested_names)) { for (int i = 0; i < nested_names.Length; i++) typedef = Mixin.GetNestedType(typedef, nested_names[i]); } type = typedef; return true; } static bool TryCurrentModule(ModuleDefinition module, Type type_info) { if (string.IsNullOrEmpty(type_info.assembly)) return true; if (module.assembly != null && module.assembly.Name.FullName == type_info.assembly) return true; return false; } public static string ToParseable(TypeReference type) { if (type == null) return null; var name = new StringBuilder(); AppendType(type, name, true, true); return name.ToString(); } static void AppendType(TypeReference type, StringBuilder name, bool fq_name, bool top_level) { var declaring_type = type.DeclaringType; if (declaring_type != null) { AppendType(declaring_type, name, false, top_level); name.Append('+'); } var @namespace = type.Namespace; if (!string.IsNullOrEmpty(@namespace)) { name.Append(@namespace); name.Append('.'); } name.Append(type.GetElementType().Name); if (!fq_name) return; if (Mixin.IsTypeSpecification(type)) AppendTypeSpecification((TypeSpecification)type, name); if (RequiresFullyQualifiedName(type, top_level)) { name.Append(", "); name.Append(GetScopeFullName(type)); } } static string GetScopeFullName(TypeReference type) { var scope = type.Scope; switch (scope.MetadataScopeType) { case MetadataScopeType.AssemblyNameReference: return ((AssemblyNameReference)scope).FullName; case MetadataScopeType.ModuleDefinition: return ((ModuleDefinition)scope).Assembly.Name.FullName; } throw new ArgumentException(); } static void AppendTypeSpecification(TypeSpecification type, StringBuilder name) { if (Mixin.IsTypeSpecification(type.ElementType)) AppendTypeSpecification((TypeSpecification)type.ElementType, name); switch (type.etype) { case ElementType.Ptr: name.Append('*'); break; case ElementType.ByRef: name.Append('&'); break; case ElementType.SzArray: case ElementType.Array: var array = (ArrayType)type; if (array.IsVector) { name.Append("[]"); } else { name.Append('['); for (int i = 1; i < array.Rank; i++) name.Append(','); name.Append(']'); } break; case ElementType.GenericInst: var instance = (GenericInstanceType)type; var arguments = instance.GenericArguments; name.Append('['); for (int i = 0; i < arguments.Count; i++) { if (i > 0) name.Append(','); var argument = arguments[i]; var requires_fqname = argument.Scope != argument.Module; if (requires_fqname) name.Append('['); AppendType(argument, name, true, false); if (requires_fqname) name.Append(']'); } name.Append(']'); break; default: return; } } static bool RequiresFullyQualifiedName(TypeReference type, bool top_level) { if (type.Scope == type.Module) return false; if (type.Scope.Name == "mscorlib" && top_level) return false; return true; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/TypeReference.cs ================================================ // // TypeReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.Metadata; using Mono.Collections.Generic; namespace Mono.Cecil { public enum MetadataType : byte { Void = ElementType.Void, Boolean = ElementType.Boolean, Char = ElementType.Char, SByte = ElementType.I1, Byte = ElementType.U1, Int16 = ElementType.I2, UInt16 = ElementType.U2, Int32 = ElementType.I4, UInt32 = ElementType.U4, Int64 = ElementType.I8, UInt64 = ElementType.U8, Single = ElementType.R4, Double = ElementType.R8, String = ElementType.String, Pointer = ElementType.Ptr, ByReference = ElementType.ByRef, ValueType = ElementType.ValueType, Class = ElementType.Class, Var = ElementType.Var, Array = ElementType.Array, GenericInstance = ElementType.GenericInst, TypedByReference = ElementType.TypedByRef, IntPtr = ElementType.I, UIntPtr = ElementType.U, FunctionPointer = ElementType.FnPtr, Object = ElementType.Object, MVar = ElementType.MVar, RequiredModifier = ElementType.CModReqD, OptionalModifier = ElementType.CModOpt, Sentinel = ElementType.Sentinel, Pinned = ElementType.Pinned, } public class TypeReference : MemberReference, IGenericParameterProvider, IGenericContext { string @namespace; bool value_type; int hashCode = -1; static int instance_id; internal IMetadataScope scope; internal ModuleDefinition module; internal ElementType etype = ElementType.None; string fullname; protected Collection generic_parameters; public override string Name { get { return base.Name; } set { base.Name = value; fullname = null; } } public virtual string Namespace { get { return @namespace; } set { @namespace = value; fullname = null; } } public virtual bool IsValueType { get { return value_type; } set { value_type = value; } } public override ModuleDefinition Module { get { if (module != null) return module; var declaring_type = this.DeclaringType; if (declaring_type != null) return declaring_type.Module; return null; } } IGenericParameterProvider IGenericContext.Type { get { return this; } } IGenericParameterProvider IGenericContext.Method { get { return null; } } GenericParameterType IGenericParameterProvider.GenericParameterType { get { return GenericParameterType.Type; } } public virtual bool HasGenericParameters { get { return !Mixin.IsNullOrEmpty(generic_parameters); } } public virtual Collection GenericParameters { get { if (generic_parameters != null) return generic_parameters; return generic_parameters = new GenericParameterCollection(this); } } public virtual IMetadataScope Scope { get { var declaring_type = this.DeclaringType; if (declaring_type != null) return declaring_type.Scope; return scope; } } public bool IsNested { get { return this.DeclaringType != null; } } public override TypeReference DeclaringType { get { return base.DeclaringType; } set { base.DeclaringType = value; fullname = null; } } public override string FullName { get { if (fullname != null) return fullname; if (IsNested) return fullname = DeclaringType.FullName + "/" + Name; if (string.IsNullOrEmpty(@namespace)) return fullname = Name; return fullname = @namespace + "." + Name; } } public virtual bool IsByReference { get { return false; } } public virtual bool IsPointer { get { return false; } } public virtual bool IsSentinel { get { return false; } } public virtual bool IsArray { get { return false; } } public virtual bool IsGenericParameter { get { return false; } } public virtual bool IsGenericInstance { get { return false; } } public virtual bool IsRequiredModifier { get { return false; } } public virtual bool IsOptionalModifier { get { return false; } } public virtual bool IsPinned { get { return false; } } public virtual bool IsFunctionPointer { get { return false; } } public override int GetHashCode() { if (hashCode == -1) hashCode = System.Threading.Interlocked.Add(ref instance_id, 1); return hashCode; } public virtual bool IsPrimitive { get { return Mixin.IsPrimitive(etype); } } public virtual MetadataType MetadataType { get { switch (etype) { case ElementType.None: return IsValueType ? MetadataType.ValueType : MetadataType.Class; default: return (MetadataType)etype; } } } protected TypeReference(string @namespace, string name) : base(name) { this.@namespace = @namespace ?? string.Empty; this.token = new MetadataToken(TokenType.TypeRef, 0); } public TypeReference(string @namespace, string name, ModuleDefinition module, IMetadataScope scope) : this(@namespace, name) { this.module = module; this.scope = scope; } public TypeReference(string @namespace, string name, ModuleDefinition module, IMetadataScope scope, bool valueType) : this(@namespace, name, module, scope) { value_type = valueType; } public virtual TypeReference GetElementType() { return this; } public virtual TypeDefinition Resolve() { var module = this.Module; if (module == null) throw new NotSupportedException(); return module.Resolve(this); } } static partial class Mixin { public static bool IsPrimitive(ElementType self) { switch (self) { case ElementType.Boolean: case ElementType.Char: case ElementType.I: case ElementType.U: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: return true; default: return false; } } public static bool IsTypeOf(TypeReference self, string @namespace, string name) { return self.Name == name && self.Namespace == @namespace; } public static bool IsTypeSpecification(TypeReference type) { switch (type.etype) { case ElementType.Array: case ElementType.ByRef: case ElementType.CModOpt: case ElementType.CModReqD: case ElementType.FnPtr: case ElementType.GenericInst: case ElementType.MVar: case ElementType.Pinned: case ElementType.Ptr: case ElementType.SzArray: case ElementType.Sentinel: case ElementType.Var: return true; } return false; } public static TypeDefinition CheckedResolve(TypeReference self) { var type = self.Resolve(); if (type == null) throw new ResolutionException(self); return type; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/TypeSpecification.cs ================================================ // // TypeSpecification.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.Metadata; namespace Mono.Cecil { public abstract class TypeSpecification : TypeReference { readonly TypeReference element_type; public TypeReference ElementType { get { return element_type; } } public override string Name { get { return element_type.Name; } set { throw new NotSupportedException (); } } public override string Namespace { get { return element_type.Namespace; } set { throw new NotSupportedException (); } } public override IMetadataScope Scope { get { return element_type.Scope; } } public override ModuleDefinition Module { get { return element_type.Module; } } public override string FullName { get { return element_type.FullName; } } internal override bool ContainsGenericParameter { get { return element_type.ContainsGenericParameter; } } public override MetadataType MetadataType { get { return (MetadataType) etype; } } internal TypeSpecification (TypeReference type) : base (null, null) { this.element_type = type; this.token = new MetadataToken (TokenType.TypeSpec); } public override TypeReference GetElementType () { return element_type; } } static partial class Mixin { public static void CheckType (TypeReference type) { if (type == null) throw new ArgumentNullException ("type"); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/TypeSystem.cs ================================================ // // TypeSystem.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.Metadata; namespace Mono.Cecil { public abstract class TypeSystem { sealed class CoreTypeSystem : TypeSystem { public CoreTypeSystem(ModuleDefinition module) : base(module) { } internal override TypeReference LookupType(string @namespace, string name) { var type = LookupTypeDefinition(@namespace, name) ?? LookupTypeForwarded(@namespace, name); if (type != null) return type; throw new NotSupportedException(); } TypeReference LookupTypeDefinition(string @namespace, string name) { var metadata = module.MetadataSystem; if (metadata.Types == null) Initialize(module.Types); return module.Read(new Row(@namespace, name), (row, reader) => { var types = reader.metadata.Types; for (int i = 0; i < types.Length; i++) { if (types[i] == null) types[i] = reader.GetTypeDefinition((uint)i + 1); var type = types[i]; if (type.Name == row.Col2 && type.Namespace == row.Col1) return type; } return null; }); } TypeReference LookupTypeForwarded(string @namespace, string name) { if (!module.HasExportedTypes) return null; var exported_types = module.ExportedTypes; for (int i = 0; i < exported_types.Count; i++) { var exported_type = exported_types[i]; if (exported_type.Name == name && exported_type.Namespace == @namespace) return exported_type.CreateReference(); } return null; } static void Initialize(object obj) { } } sealed class CommonTypeSystem : TypeSystem { AssemblyNameReference corlib; public CommonTypeSystem(ModuleDefinition module) : base(module) { } internal override TypeReference LookupType(string @namespace, string name) { return CreateTypeReference(@namespace, name); } public AssemblyNameReference GetCorlibReference() { if (corlib != null) return corlib; const string mscorlib = "mscorlib"; const string systemruntime = "System.Runtime"; var references = module.AssemblyReferences; for (int i = 0; i < references.Count; i++) { var reference = references[i]; if (reference.Name == mscorlib || reference.Name == systemruntime) return corlib = reference; } corlib = new AssemblyNameReference { Name = mscorlib, Version = GetCorlibVersion(), PublicKeyToken = new byte[] { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 }, }; references.Add(corlib); return corlib; } Version GetCorlibVersion() { switch (module.Runtime) { case TargetRuntime.Net_1_0: case TargetRuntime.Net_1_1: return new Version(1, 0, 0, 0); case TargetRuntime.Net_2_0: return new Version(2, 0, 0, 0); case TargetRuntime.Net_4_0: return new Version(4, 0, 0, 0); default: throw new NotSupportedException(); } } TypeReference CreateTypeReference(string @namespace, string name) { return new TypeReference(@namespace, name, module, GetCorlibReference()); } } readonly ModuleDefinition module; TypeReference type_object; TypeReference type_void; TypeReference type_bool; TypeReference type_char; TypeReference type_sbyte; TypeReference type_byte; TypeReference type_int16; TypeReference type_uint16; TypeReference type_int32; TypeReference type_uint32; TypeReference type_int64; TypeReference type_uint64; TypeReference type_single; TypeReference type_double; TypeReference type_intptr; TypeReference type_uintptr; TypeReference type_string; TypeReference type_typedref; TypeSystem(ModuleDefinition module) { this.module = module; } internal static TypeSystem CreateTypeSystem(ModuleDefinition module) { if (Mixin.IsCorlib(module)) return new CoreTypeSystem(module); return new CommonTypeSystem(module); } internal abstract TypeReference LookupType(string @namespace, string name); TypeReference LookupSystemType(ref TypeReference typeRef, string name, ElementType element_type) { lock (module.SyncRoot) { if (typeRef != null) return typeRef; var type = LookupType("System", name); type.etype = element_type; return typeRef = type; } } TypeReference LookupSystemValueType(ref TypeReference typeRef, string name, ElementType element_type) { lock (module.SyncRoot) { if (typeRef != null) return typeRef; var type = LookupType("System", name); type.etype = element_type; type.IsValueType = true; return typeRef = type; } } public IMetadataScope Corlib { get { var common = this as CommonTypeSystem; if (common == null) return module; return common.GetCorlibReference(); } } public TypeReference Object { get { return type_object ?? (LookupSystemType(ref type_object, "Object", ElementType.Object)); } } public TypeReference Void { get { return type_void ?? (LookupSystemType(ref type_void, "Void", ElementType.Void)); } } public TypeReference Boolean { get { return type_bool ?? (LookupSystemValueType(ref type_bool, "Boolean", ElementType.Boolean)); } } public TypeReference Char { get { return type_char ?? (LookupSystemValueType(ref type_char, "Char", ElementType.Char)); } } public TypeReference SByte { get { return type_sbyte ?? (LookupSystemValueType(ref type_sbyte, "SByte", ElementType.I1)); } } public TypeReference Byte { get { return type_byte ?? (LookupSystemValueType(ref type_byte, "Byte", ElementType.U1)); } } public TypeReference Int16 { get { return type_int16 ?? (LookupSystemValueType(ref type_int16, "Int16", ElementType.I2)); } } public TypeReference UInt16 { get { return type_uint16 ?? (LookupSystemValueType(ref type_uint16, "UInt16", ElementType.U2)); } } public TypeReference Int32 { get { return type_int32 ?? (LookupSystemValueType(ref type_int32, "Int32", ElementType.I4)); } } public TypeReference UInt32 { get { return type_uint32 ?? (LookupSystemValueType(ref type_uint32, "UInt32", ElementType.U4)); } } public TypeReference Int64 { get { return type_int64 ?? (LookupSystemValueType(ref type_int64, "Int64", ElementType.I8)); } } public TypeReference UInt64 { get { return type_uint64 ?? (LookupSystemValueType(ref type_uint64, "UInt64", ElementType.U8)); } } public TypeReference Single { get { return type_single ?? (LookupSystemValueType(ref type_single, "Single", ElementType.R4)); } } public TypeReference Double { get { return type_double ?? (LookupSystemValueType(ref type_double, "Double", ElementType.R8)); } } public TypeReference IntPtr { get { return type_intptr ?? (LookupSystemValueType(ref type_intptr, "IntPtr", ElementType.I)); } } public TypeReference UIntPtr { get { return type_uintptr ?? (LookupSystemValueType(ref type_uintptr, "UIntPtr", ElementType.U)); } } public TypeReference String { get { return type_string ?? (LookupSystemType(ref type_string, "String", ElementType.String)); } } public TypeReference TypedReference { get { return type_typedref ?? (LookupSystemValueType(ref type_typedref, "TypedReference", ElementType.TypedByRef)); } } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil/VariantType.cs ================================================ // // VariantType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public enum VariantType { None = 0, I2 = 2, I4 = 3, R4 = 4, R8 = 5, CY = 6, Date = 7, BStr = 8, Dispatch = 9, Error = 10, Bool = 11, Variant = 12, Unknown = 13, Decimal = 14, I1 = 16, UI1 = 17, UI2 = 18, UI4 = 19, Int = 22, UInt = 23 } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/Code.cs ================================================ // // Code.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil.Cil { public enum Code { Nop, Break, Ldarg_0, Ldarg_1, Ldarg_2, Ldarg_3, Ldloc_0, Ldloc_1, Ldloc_2, Ldloc_3, Stloc_0, Stloc_1, Stloc_2, Stloc_3, Ldarg_S, Ldarga_S, Starg_S, Ldloc_S, Ldloca_S, Stloc_S, Ldnull, Ldc_I4_M1, Ldc_I4_0, Ldc_I4_1, Ldc_I4_2, Ldc_I4_3, Ldc_I4_4, Ldc_I4_5, Ldc_I4_6, Ldc_I4_7, Ldc_I4_8, Ldc_I4_S, Ldc_I4, Ldc_I8, Ldc_R4, Ldc_R8, Dup, Pop, Jmp, Call, Calli, Ret, Br_S, Brfalse_S, Brtrue_S, Beq_S, Bge_S, Bgt_S, Ble_S, Blt_S, Bne_Un_S, Bge_Un_S, Bgt_Un_S, Ble_Un_S, Blt_Un_S, Br, Brfalse, Brtrue, Beq, Bge, Bgt, Ble, Blt, Bne_Un, Bge_Un, Bgt_Un, Ble_Un, Blt_Un, Switch, Ldind_I1, Ldind_U1, Ldind_I2, Ldind_U2, Ldind_I4, Ldind_U4, Ldind_I8, Ldind_I, Ldind_R4, Ldind_R8, Ldind_Ref, Stind_Ref, Stind_I1, Stind_I2, Stind_I4, Stind_I8, Stind_R4, Stind_R8, Add, Sub, Mul, Div, Div_Un, Rem, Rem_Un, And, Or, Xor, Shl, Shr, Shr_Un, Neg, Not, Conv_I1, Conv_I2, Conv_I4, Conv_I8, Conv_R4, Conv_R8, Conv_U4, Conv_U8, Callvirt, Cpobj, Ldobj, Ldstr, Newobj, Castclass, Isinst, Conv_R_Un, Unbox, Throw, Ldfld, Ldflda, Stfld, Ldsfld, Ldsflda, Stsfld, Stobj, Conv_Ovf_I1_Un, Conv_Ovf_I2_Un, Conv_Ovf_I4_Un, Conv_Ovf_I8_Un, Conv_Ovf_U1_Un, Conv_Ovf_U2_Un, Conv_Ovf_U4_Un, Conv_Ovf_U8_Un, Conv_Ovf_I_Un, Conv_Ovf_U_Un, Box, Newarr, Ldlen, Ldelema, Ldelem_I1, Ldelem_U1, Ldelem_I2, Ldelem_U2, Ldelem_I4, Ldelem_U4, Ldelem_I8, Ldelem_I, Ldelem_R4, Ldelem_R8, Ldelem_Ref, Stelem_I, Stelem_I1, Stelem_I2, Stelem_I4, Stelem_I8, Stelem_R4, Stelem_R8, Stelem_Ref, Ldelem_Any, Stelem_Any, Unbox_Any, Conv_Ovf_I1, Conv_Ovf_U1, Conv_Ovf_I2, Conv_Ovf_U2, Conv_Ovf_I4, Conv_Ovf_U4, Conv_Ovf_I8, Conv_Ovf_U8, Refanyval, Ckfinite, Mkrefany, Ldtoken, Conv_U2, Conv_U1, Conv_I, Conv_Ovf_I, Conv_Ovf_U, Add_Ovf, Add_Ovf_Un, Mul_Ovf, Mul_Ovf_Un, Sub_Ovf, Sub_Ovf_Un, Endfinally, Leave, Leave_S, Stind_I, Conv_U, Arglist, Ceq, Cgt, Cgt_Un, Clt, Clt_Un, Ldftn, Ldvirtftn, Ldarg, Ldarga, Starg, Ldloc, Ldloca, Stloc, Localloc, Endfilter, Unaligned, Volatile, Tail, Initobj, Constrained, Cpblk, Initblk, No, Rethrow, Sizeof, Refanytype, Readonly, } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/CodeReader.cs ================================================ // // CodeReader.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.PE; using Mono.Collections.Generic; using RVA = System.UInt32; namespace Mono.Cecil.Cil { sealed class CodeReader : ByteBuffer { readonly internal MetadataReader reader; int start; Section code_section; MethodDefinition method; MethodBody body; int Offset { get { return base.position - start; } } public CodeReader(Section section, MetadataReader reader) : base(section.Data) { this.code_section = section; this.reader = reader; } public MethodBody ReadMethodBody(MethodDefinition method) { this.method = method; this.body = new MethodBody(method); reader.context = method; ReadMethodBody(); return this.body; } public void MoveTo(int rva) { if (!IsInSection(rva)) { code_section = reader.image.GetSectionAtVirtualAddress((uint)rva); Reset(code_section.Data); } base.position = rva - (int)code_section.VirtualAddress; } bool IsInSection(int rva) { return code_section.VirtualAddress <= rva && rva < code_section.VirtualAddress + code_section.SizeOfRawData; } void ReadMethodBody() { MoveTo(method.RVA); var flags = ReadByte(); switch (flags & 0x3) { case 0x2: // tiny body.code_size = flags >> 2; body.MaxStackSize = 8; ReadCode(); break; case 0x3: // fat base.position--; ReadFatMethod(); break; default: throw new InvalidOperationException(); } var symbol_reader = reader.module.symbol_reader; if (symbol_reader != null) { var instructions = body.Instructions; symbol_reader.Read(body, offset => GetInstruction(instructions, offset)); } } void ReadFatMethod() { var flags = ReadUInt16(); body.max_stack_size = ReadUInt16(); body.code_size = (int)ReadUInt32(); body.local_var_token = new MetadataToken(ReadUInt32()); body.init_locals = (flags & 0x10) != 0; if (body.local_var_token.RID != 0) body.variables = ReadVariables(body.local_var_token); ReadCode(); if ((flags & 0x8) != 0) ReadSection(); } public VariableDefinitionCollection ReadVariables(MetadataToken local_var_token) { var position = reader.position; var variables = reader.ReadVariables(local_var_token); reader.position = position; return variables; } void ReadCode() { start = position; var code_size = body.code_size; if (code_size < 0 || buffer.Length <= (uint)(code_size + position)) code_size = 0; var end = start + code_size; var instructions = body.instructions = new InstructionCollection((code_size + 1) / 2); while (position < end) { var offset = base.position - start; var opcode = ReadOpCode(); var current = new Instruction(offset, opcode); if (opcode.OperandType != OperandType.InlineNone) current.operand = ReadOperand(current); instructions.Add(current); } ResolveBranches(instructions); } OpCode ReadOpCode() { var il_opcode = ReadByte(); return il_opcode != 0xfe ? OpCodes.OneByteOpCode[il_opcode] : OpCodes.TwoBytesOpCode[ReadByte()]; } object ReadOperand(Instruction instruction) { switch (instruction.opcode.OperandType) { case OperandType.InlineSwitch: var length = ReadInt32(); var base_offset = Offset + (4 * length); var branches = new int[length]; for (int i = 0; i < length; i++) branches[i] = base_offset + ReadInt32(); return branches; case OperandType.ShortInlineBrTarget: return ReadSByte() + Offset; case OperandType.InlineBrTarget: return ReadInt32() + Offset; case OperandType.ShortInlineI: if (instruction.opcode == OpCodes.Ldc_I4_S) return ReadSByte(); return ReadByte(); case OperandType.InlineI: return ReadInt32(); case OperandType.ShortInlineR: return ReadSingle(); case OperandType.InlineR: return ReadDouble(); case OperandType.InlineI8: return ReadInt64(); case OperandType.ShortInlineVar: return GetVariable(ReadByte()); case OperandType.InlineVar: return GetVariable(ReadUInt16()); case OperandType.ShortInlineArg: return GetParameter(ReadByte()); case OperandType.InlineArg: return GetParameter(ReadUInt16()); case OperandType.InlineSig: return GetCallSite(ReadToken()); case OperandType.InlineString: return GetString(ReadToken()); case OperandType.InlineTok: case OperandType.InlineType: case OperandType.InlineMethod: case OperandType.InlineField: return reader.LookupToken(ReadToken()); default: throw new NotSupportedException(); } } public string GetString(MetadataToken token) { return reader.image.UserStringHeap.Read(token.RID); } public ParameterDefinition GetParameter(int index) { return Mixin.GetParameter(body, index); } public VariableDefinition GetVariable(int index) { return Mixin.GetVariable(body, index); } public CallSite GetCallSite(MetadataToken token) { return reader.ReadCallSite(token); } void ResolveBranches(Collection instructions) { var items = instructions.items; var size = instructions.size; for (int i = 0; i < size; i++) { var instruction = items[i]; switch (instruction.opcode.OperandType) { case OperandType.ShortInlineBrTarget: case OperandType.InlineBrTarget: instruction.operand = GetInstruction((int)instruction.operand); break; case OperandType.InlineSwitch: var offsets = (int[])instruction.operand; var branches = new Instruction[offsets.Length]; for (int j = 0; j < offsets.Length; j++) branches[j] = GetInstruction(offsets[j]); instruction.operand = branches; break; } } } Instruction GetInstruction(int offset) { return GetInstruction(body.Instructions, offset); } static Instruction GetInstruction(Collection instructions, int offset) { var size = instructions.size; var items = instructions.items; if (offset < 0 || offset > items[size - 1].offset) return null; int min = 0; int max = size - 1; while (min <= max) { int mid = min + ((max - min) / 2); var instruction = items[mid]; var instruction_offset = instruction.offset; if (offset == instruction_offset) return instruction; if (offset < instruction_offset) max = mid - 1; else min = mid + 1; } return null; } void ReadSection() { Align(4); const byte fat_format = 0x40; const byte more_sects = 0x80; var flags = ReadByte(); if ((flags & fat_format) == 0) ReadSmallSection(); else ReadFatSection(); if ((flags & more_sects) != 0) ReadSection(); } void ReadSmallSection() { var count = ReadByte() / 12; Advance(2); ReadExceptionHandlers( count, () => (int)ReadUInt16(), () => (int)ReadByte()); } void ReadFatSection() { position--; var count = (ReadInt32() >> 8) / 24; ReadExceptionHandlers( count, ReadInt32, ReadInt32); } // inline ? void ReadExceptionHandlers(int count, Func read_entry, Func read_length) { for (int i = 0; i < count; i++) { var handler = new ExceptionHandler( (ExceptionHandlerType)(read_entry() & 0x7)); handler.TryStart = GetInstruction(read_entry()); handler.TryEnd = GetInstruction(handler.TryStart.Offset + read_length()); handler.HandlerStart = GetInstruction(read_entry()); handler.HandlerEnd = GetInstruction(handler.HandlerStart.Offset + read_length()); ReadExceptionHandlerSpecific(handler); this.body.ExceptionHandlers.Add(handler); } } void ReadExceptionHandlerSpecific(ExceptionHandler handler) { switch (handler.HandlerType) { case ExceptionHandlerType.Catch: handler.CatchType = (TypeReference)reader.LookupToken(ReadToken()); break; case ExceptionHandlerType.Filter: handler.FilterStart = GetInstruction(ReadInt32()); break; default: Advance(4); break; } } void Align(int align) { align--; Advance(((position + align) & ~align) - position); } public MetadataToken ReadToken() { return new MetadataToken(ReadUInt32()); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/CodeWriter.cs ================================================ // // CodeWriter.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using Mono.Collections.Generic; using Mono.Cecil.Metadata; using Mono.Cecil.PE; using RVA = System.UInt32; ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/Document.cs ================================================ // // Document.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil.Cil { public enum DocumentType { Other, Text, } public enum DocumentHashAlgorithm { None, MD5, SHA1, } public enum DocumentLanguage { Other, C, Cpp, CSharp, Basic, Java, Cobol, Pascal, Cil, JScript, Smc, MCpp, FSharp, } public enum DocumentLanguageVendor { Other, Microsoft, } public sealed class Document { string url; byte type; byte hash_algorithm; byte language; byte language_vendor; byte [] hash; public string Url { get { return url; } set { url = value; } } public DocumentType Type { get { return (DocumentType) type; } set { type = (byte) value; } } public DocumentHashAlgorithm HashAlgorithm { get { return (DocumentHashAlgorithm) hash_algorithm; } set { hash_algorithm = (byte) value; } } public DocumentLanguage Language { get { return (DocumentLanguage) language; } set { language = (byte) value; } } public DocumentLanguageVendor LanguageVendor { get { return (DocumentLanguageVendor) language_vendor; } set { language_vendor = (byte) value; } } public byte [] Hash { get { return hash; } set { hash = value; } } public Document (string url) { this.url = url; this.hash = Empty.Array; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/ExceptionHandler.cs ================================================ // // ExceptionHandler.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil.Cil { public enum ExceptionHandlerType { Catch = 0, Filter = 1, Finally = 2, Fault = 4, } public sealed class ExceptionHandler { Instruction try_start; Instruction try_end; Instruction filter_start; Instruction handler_start; Instruction handler_end; TypeReference catch_type; ExceptionHandlerType handler_type; public Instruction TryStart { get { return try_start; } set { try_start = value; } } public Instruction TryEnd { get { return try_end; } set { try_end = value; } } public Instruction FilterStart { get { return filter_start; } set { filter_start = value; } } public Instruction HandlerStart { get { return handler_start; } set { handler_start = value; } } public Instruction HandlerEnd { get { return handler_end; } set { handler_end = value; } } public TypeReference CatchType { get { return catch_type; } set { catch_type = value; } } public ExceptionHandlerType HandlerType { get { return handler_type; } set { handler_type = value; } } public ExceptionHandler (ExceptionHandlerType handlerType) { this.handler_type = handlerType; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/ILProcessor.cs ================================================ // // ILProcessor.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Collections.Generic; namespace Mono.Cecil.Cil { public sealed class ILProcessor { readonly MethodBody body; readonly Collection instructions; public MethodBody Body { get { return body; } } internal ILProcessor (MethodBody body) { this.body = body; this.instructions = body.Instructions; } public Instruction Create (OpCode opcode) { return Instruction.Create (opcode); } public Instruction Create (OpCode opcode, TypeReference type) { return Instruction.Create (opcode, type); } public Instruction Create (OpCode opcode, CallSite site) { return Instruction.Create (opcode, site); } public Instruction Create (OpCode opcode, MethodReference method) { return Instruction.Create (opcode, method); } public Instruction Create (OpCode opcode, FieldReference field) { return Instruction.Create (opcode, field); } public Instruction Create (OpCode opcode, string value) { return Instruction.Create (opcode, value); } public Instruction Create (OpCode opcode, sbyte value) { return Instruction.Create (opcode, value); } public Instruction Create (OpCode opcode, byte value) { if (opcode.OperandType == OperandType.ShortInlineVar) return Instruction.Create (opcode, body.Variables [value]); if (opcode.OperandType == OperandType.ShortInlineArg) return Instruction.Create (opcode, Mixin.GetParameter (body,value)); return Instruction.Create (opcode, value); } public Instruction Create (OpCode opcode, int value) { if (opcode.OperandType == OperandType.InlineVar) return Instruction.Create (opcode, body.Variables [value]); if (opcode.OperandType == OperandType.InlineArg) return Instruction.Create (opcode, Mixin.GetParameter (body,value)); return Instruction.Create (opcode, value); } public Instruction Create (OpCode opcode, long value) { return Instruction.Create (opcode, value); } public Instruction Create (OpCode opcode, float value) { return Instruction.Create (opcode, value); } public Instruction Create (OpCode opcode, double value) { return Instruction.Create (opcode, value); } public Instruction Create (OpCode opcode, Instruction target) { return Instruction.Create (opcode, target); } public Instruction Create (OpCode opcode, Instruction [] targets) { return Instruction.Create (opcode, targets); } public Instruction Create (OpCode opcode, VariableDefinition variable) { return Instruction.Create (opcode, variable); } public Instruction Create (OpCode opcode, ParameterDefinition parameter) { return Instruction.Create (opcode, parameter); } public void Emit (OpCode opcode) { Append (Create (opcode)); } public void Emit (OpCode opcode, TypeReference type) { Append (Create (opcode, type)); } public void Emit (OpCode opcode, MethodReference method) { Append (Create (opcode, method)); } public void Emit (OpCode opcode, CallSite site) { Append (Create (opcode, site)); } public void Emit (OpCode opcode, FieldReference field) { Append (Create (opcode, field)); } public void Emit (OpCode opcode, string value) { Append (Create (opcode, value)); } public void Emit (OpCode opcode, byte value) { Append (Create (opcode, value)); } public void Emit (OpCode opcode, sbyte value) { Append (Create (opcode, value)); } public void Emit (OpCode opcode, int value) { Append (Create (opcode, value)); } public void Emit (OpCode opcode, long value) { Append (Create (opcode, value)); } public void Emit (OpCode opcode, float value) { Append (Create (opcode, value)); } public void Emit (OpCode opcode, double value) { Append (Create (opcode, value)); } public void Emit (OpCode opcode, Instruction target) { Append (Create (opcode, target)); } public void Emit (OpCode opcode, Instruction [] targets) { Append (Create (opcode, targets)); } public void Emit (OpCode opcode, VariableDefinition variable) { Append (Create (opcode, variable)); } public void Emit (OpCode opcode, ParameterDefinition parameter) { Append (Create (opcode, parameter)); } public void InsertBefore (Instruction target, Instruction instruction) { if (target == null) throw new ArgumentNullException ("target"); if (instruction == null) throw new ArgumentNullException ("instruction"); var index = instructions.IndexOf (target); if (index == -1) throw new ArgumentOutOfRangeException ("target"); instructions.Insert (index, instruction); } public void InsertAfter (Instruction target, Instruction instruction) { if (target == null) throw new ArgumentNullException ("target"); if (instruction == null) throw new ArgumentNullException ("instruction"); var index = instructions.IndexOf (target); if (index == -1) throw new ArgumentOutOfRangeException ("target"); instructions.Insert (index + 1, instruction); } public void Append (Instruction instruction) { if (instruction == null) throw new ArgumentNullException ("instruction"); instructions.Add (instruction); } public void Replace (Instruction target, Instruction instruction) { if (target == null) throw new ArgumentNullException ("target"); if (instruction == null) throw new ArgumentNullException ("instruction"); InsertAfter (target, instruction); Remove (target); } public void Remove (Instruction instruction) { if (instruction == null) throw new ArgumentNullException ("instruction"); if (!instructions.Remove (instruction)) throw new ArgumentOutOfRangeException ("instruction"); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/Instruction.cs ================================================ // // Instruction.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Text; namespace Mono.Cecil.Cil { public sealed class Instruction { internal int offset; internal OpCode opcode; internal object operand; internal Instruction previous; internal Instruction next; SequencePoint sequence_point; public int Offset { get { return offset; } set { offset = value; } } public OpCode OpCode { get { return opcode; } set { opcode = value; } } public object Operand { get { return operand; } set { operand = value; } } public Instruction Previous { get { return previous; } set { previous = value; } } public Instruction Next { get { return next; } set { next = value; } } public SequencePoint SequencePoint { get { return sequence_point; } set { sequence_point = value; } } internal Instruction (int offset, OpCode opCode) { this.offset = offset; this.opcode = opCode; } internal Instruction (OpCode opcode, object operand) { this.opcode = opcode; this.operand = operand; } public int GetSize () { int size = opcode.Size; switch (opcode.OperandType) { case OperandType.InlineSwitch: return size + (1 + ((Instruction []) operand).Length) * 4; case OperandType.InlineI8: case OperandType.InlineR: return size + 8; case OperandType.InlineBrTarget: case OperandType.InlineField: case OperandType.InlineI: case OperandType.InlineMethod: case OperandType.InlineString: case OperandType.InlineTok: case OperandType.InlineType: case OperandType.ShortInlineR: case OperandType.InlineSig: return size + 4; case OperandType.InlineArg: case OperandType.InlineVar: return size + 2; case OperandType.ShortInlineBrTarget: case OperandType.ShortInlineI: case OperandType.ShortInlineArg: case OperandType.ShortInlineVar: return size + 1; default: return size; } } public override string ToString () { var instruction = new StringBuilder (); AppendLabel (instruction, this); instruction.Append (':'); instruction.Append (' '); instruction.Append (opcode.Name); if (operand == null) return instruction.ToString (); instruction.Append (' '); switch (opcode.OperandType) { case OperandType.ShortInlineBrTarget: case OperandType.InlineBrTarget: AppendLabel (instruction, (Instruction) operand); break; case OperandType.InlineSwitch: var labels = (Instruction []) operand; for (int i = 0; i < labels.Length; i++) { if (i > 0) instruction.Append (','); AppendLabel (instruction, labels [i]); } break; case OperandType.InlineString: instruction.Append ('\"'); instruction.Append (operand); instruction.Append ('\"'); break; default: instruction.Append (operand); break; } return instruction.ToString (); } static void AppendLabel (StringBuilder builder, Instruction instruction) { builder.Append ("IL_"); builder.Append (instruction.offset.ToString ("x4")); } public static Instruction Create (OpCode opcode) { if (opcode.OperandType != OperandType.InlineNone) throw new ArgumentException ("opcode"); return new Instruction (opcode, null); } public static Instruction Create (OpCode opcode, TypeReference type) { if (type == null) throw new ArgumentNullException ("type"); if (opcode.OperandType != OperandType.InlineType && opcode.OperandType != OperandType.InlineTok) throw new ArgumentException ("opcode"); return new Instruction (opcode, type); } public static Instruction Create (OpCode opcode, CallSite site) { if (site == null) throw new ArgumentNullException ("site"); if (opcode.Code != Code.Calli) throw new ArgumentException ("code"); return new Instruction (opcode, site); } public static Instruction Create (OpCode opcode, MethodReference method) { if (method == null) throw new ArgumentNullException ("method"); if (opcode.OperandType != OperandType.InlineMethod && opcode.OperandType != OperandType.InlineTok) throw new ArgumentException ("opcode"); return new Instruction (opcode, method); } public static Instruction Create (OpCode opcode, FieldReference field) { if (field == null) throw new ArgumentNullException ("field"); if (opcode.OperandType != OperandType.InlineField && opcode.OperandType != OperandType.InlineTok) throw new ArgumentException ("opcode"); return new Instruction (opcode, field); } public static Instruction Create (OpCode opcode, string value) { if (value == null) throw new ArgumentNullException ("value"); if (opcode.OperandType != OperandType.InlineString) throw new ArgumentException ("opcode"); return new Instruction (opcode, value); } public static Instruction Create (OpCode opcode, sbyte value) { if (opcode.OperandType != OperandType.ShortInlineI && opcode != OpCodes.Ldc_I4_S) throw new ArgumentException ("opcode"); return new Instruction (opcode, value); } public static Instruction Create (OpCode opcode, byte value) { if (opcode.OperandType != OperandType.ShortInlineI || opcode == OpCodes.Ldc_I4_S) throw new ArgumentException ("opcode"); return new Instruction (opcode, value); } public static Instruction Create (OpCode opcode, int value) { if (opcode.OperandType != OperandType.InlineI) throw new ArgumentException ("opcode"); return new Instruction (opcode, value); } public static Instruction Create (OpCode opcode, long value) { if (opcode.OperandType != OperandType.InlineI8) throw new ArgumentException ("opcode"); return new Instruction (opcode, value); } public static Instruction Create (OpCode opcode, float value) { if (opcode.OperandType != OperandType.ShortInlineR) throw new ArgumentException ("opcode"); return new Instruction (opcode, value); } public static Instruction Create (OpCode opcode, double value) { if (opcode.OperandType != OperandType.InlineR) throw new ArgumentException ("opcode"); return new Instruction (opcode, value); } public static Instruction Create (OpCode opcode, Instruction target) { if (target == null) throw new ArgumentNullException ("target"); if (opcode.OperandType != OperandType.InlineBrTarget && opcode.OperandType != OperandType.ShortInlineBrTarget) throw new ArgumentException ("opcode"); return new Instruction (opcode, target); } public static Instruction Create (OpCode opcode, Instruction [] targets) { if (targets == null) throw new ArgumentNullException ("targets"); if (opcode.OperandType != OperandType.InlineSwitch) throw new ArgumentException ("opcode"); return new Instruction (opcode, targets); } public static Instruction Create (OpCode opcode, VariableDefinition variable) { if (variable == null) throw new ArgumentNullException ("variable"); if (opcode.OperandType != OperandType.ShortInlineVar && opcode.OperandType != OperandType.InlineVar) throw new ArgumentException ("opcode"); return new Instruction (opcode, variable); } public static Instruction Create (OpCode opcode, ParameterDefinition parameter) { if (parameter == null) throw new ArgumentNullException ("parameter"); if (opcode.OperandType != OperandType.ShortInlineArg && opcode.OperandType != OperandType.InlineArg) throw new ArgumentException ("opcode"); return new Instruction (opcode, parameter); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/MethodBody.cs ================================================ // // MethodBody.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Threading; using Mono.Collections.Generic; namespace Mono.Cecil.Cil { public sealed class MethodBody : IVariableDefinitionProvider { readonly internal MethodDefinition method; internal ParameterDefinition this_parameter; internal int max_stack_size; internal int code_size; internal bool init_locals; internal MetadataToken local_var_token; internal Collection instructions; internal Collection exceptions; internal Collection variables; Scope scope; public MethodDefinition Method { get { return method; } } public int MaxStackSize { get { return max_stack_size; } set { max_stack_size = value; } } public int CodeSize { get { return code_size; } } public bool InitLocals { get { return init_locals; } set { init_locals = value; } } public MetadataToken LocalVarToken { get { return local_var_token; } set { local_var_token = value; } } public Collection Instructions { get { return instructions ?? (instructions = new InstructionCollection()); } } public bool HasExceptionHandlers { get { return !Mixin.IsNullOrEmpty(exceptions); } } public Collection ExceptionHandlers { get { return exceptions ?? (exceptions = new Collection()); } } public bool HasVariables { get { return !Mixin.IsNullOrEmpty(variables); } } public Collection Variables { get { return variables ?? (variables = new VariableDefinitionCollection()); } } public Scope Scope { get { return scope; } set { scope = value; } } public ParameterDefinition ThisParameter { get { if (method == null || method.DeclaringType == null) throw new NotSupportedException(); if (!method.HasThis) return null; if (this_parameter == null) this_parameter = ThisParameterFor(method); return this_parameter; } } static ParameterDefinition ThisParameterFor(MethodDefinition method) { var declaring_type = method.DeclaringType; var type = declaring_type.IsValueType || declaring_type.IsPrimitive ? new PointerType(declaring_type) : declaring_type as TypeReference; return new ParameterDefinition(type, method); } public MethodBody(MethodDefinition method) { this.method = method; } public ILProcessor GetILProcessor() { return new ILProcessor(this); } } public interface IVariableDefinitionProvider { bool HasVariables { get; } Collection Variables { get; } } class VariableDefinitionCollection : Collection { internal VariableDefinitionCollection() { } internal VariableDefinitionCollection(int capacity) : base(capacity) { } protected override void OnAdd(VariableDefinition item, int index) { item.index = index; } protected override void OnInsert(VariableDefinition item, int index) { item.index = index; for (int i = index; i < size; i++) items[i].index = i + 1; } protected override void OnSet(VariableDefinition item, int index) { item.index = index; } protected override void OnRemove(VariableDefinition item, int index) { item.index = -1; for (int i = index + 1; i < size; i++) items[i].index = i - 1; } } class InstructionCollection : Collection { internal InstructionCollection() { } internal InstructionCollection(int capacity) : base(capacity) { } protected override void OnAdd(Instruction item, int index) { if (index == 0) return; var previous = items[index - 1]; previous.next = item; item.previous = previous; } protected override void OnInsert(Instruction item, int index) { if (size == 0) return; var current = items[index]; if (current == null) { var last = items[index - 1]; last.next = item; item.previous = last; return; } var previous = current.previous; if (previous != null) { previous.next = item; item.previous = previous; } current.previous = item; item.next = current; } protected override void OnSet(Instruction item, int index) { var current = items[index]; item.previous = current.previous; item.next = current.next; current.previous = null; current.next = null; } protected override void OnRemove(Instruction item, int index) { var previous = item.previous; if (previous != null) previous.next = item.next; var next = item.next; if (next != null) next.previous = item.previous; item.previous = null; item.next = null; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/OpCode.cs ================================================ // // OpCode.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil.Cil { public enum FlowControl { Branch, Break, Call, Cond_Branch, Meta, Next, Phi, Return, Throw, } public enum OpCodeType { Annotation, Macro, Nternal, Objmodel, Prefix, Primitive, } public enum OperandType { InlineBrTarget, InlineField, InlineI, InlineI8, InlineMethod, InlineNone, InlinePhi, InlineR, InlineSig, InlineString, InlineSwitch, InlineTok, InlineType, InlineVar, InlineArg, ShortInlineBrTarget, ShortInlineI, ShortInlineR, ShortInlineVar, ShortInlineArg, } public enum StackBehaviour { Pop0, Pop1, Pop1_pop1, Popi, Popi_pop1, Popi_popi, Popi_popi8, Popi_popi_popi, Popi_popr4, Popi_popr8, Popref, Popref_pop1, Popref_popi, Popref_popi_popi, Popref_popi_popi8, Popref_popi_popr4, Popref_popi_popr8, Popref_popi_popref, PopAll, Push0, Push1, Push1_push1, Pushi, Pushi8, Pushr4, Pushr8, Pushref, Varpop, Varpush, } public struct OpCode { readonly byte op1; readonly byte op2; readonly byte code; readonly byte flow_control; readonly byte opcode_type; readonly byte operand_type; readonly byte stack_behavior_pop; readonly byte stack_behavior_push; public string Name { get { return OpCodeNames.names [(int) Code]; } } public int Size { get { return op1 == 0xff ? 1 : 2; } } public byte Op1 { get { return op1; } } public byte Op2 { get { return op2; } } public short Value { get { return op1 == 0xff ? op2 : (short) ((op1 << 8) | op2); } } public Code Code { get { return (Code) code; } } public FlowControl FlowControl { get { return (FlowControl) flow_control; } } public OpCodeType OpCodeType { get { return (OpCodeType) opcode_type; } } public OperandType OperandType { get { return (OperandType) operand_type; } } public StackBehaviour StackBehaviourPop { get { return (StackBehaviour) stack_behavior_pop; } } public StackBehaviour StackBehaviourPush { get { return (StackBehaviour) stack_behavior_push; } } internal OpCode (int x, int y) { this.op1 = (byte) ((x >> 0) & 0xff); this.op2 = (byte) ((x >> 8) & 0xff); this.code = (byte) ((x >> 16) & 0xff); this.flow_control = (byte) ((x >> 24) & 0xff); this.opcode_type = (byte) ((y >> 0) & 0xff); this.operand_type = (byte) ((y >> 8) & 0xff); this.stack_behavior_pop = (byte) ((y >> 16) & 0xff); this.stack_behavior_push = (byte) ((y >> 24) & 0xff); if (op1 == 0xff) OpCodes.OneByteOpCode [op2] = this; else OpCodes.TwoBytesOpCode [op2] = this; } public override int GetHashCode () { return Value; } public override bool Equals (object obj) { if (!(obj is OpCode)) return false; var opcode = (OpCode) obj; return op1 == opcode.op1 && op2 == opcode.op2; } public bool Equals (OpCode opcode) { return op1 == opcode.op1 && op2 == opcode.op2; } public static bool operator == (OpCode one, OpCode other) { return one.op1 == other.op1 && one.op2 == other.op2; } public static bool operator != (OpCode one, OpCode other) { return one.op1 != other.op1 || one.op2 != other.op2; } public override string ToString () { return Name; } } static class OpCodeNames { internal static readonly string [] names; static OpCodeNames () { var table = new byte [] { 3, 110, 111, 112, 5, 98, 114, 101, 97, 107, 7, 108, 100, 97, 114, 103, 46, 48, 7, 108, 100, 97, 114, 103, 46, 49, 7, 108, 100, 97, 114, 103, 46, 50, 7, 108, 100, 97, 114, 103, 46, 51, 7, 108, 100, 108, 111, 99, 46, 48, 7, 108, 100, 108, 111, 99, 46, 49, 7, 108, 100, 108, 111, 99, 46, 50, 7, 108, 100, 108, 111, 99, 46, 51, 7, 115, 116, 108, 111, 99, 46, 48, 7, 115, 116, 108, 111, 99, 46, 49, 7, 115, 116, 108, 111, 99, 46, 50, 7, 115, 116, 108, 111, 99, 46, 51, 7, 108, 100, 97, 114, 103, 46, 115, 8, 108, 100, 97, 114, 103, 97, 46, 115, 7, 115, 116, 97, 114, 103, 46, 115, 7, 108, 100, 108, 111, 99, 46, 115, 8, 108, 100, 108, 111, 99, 97, 46, 115, 7, 115, 116, 108, 111, 99, 46, 115, 6, 108, 100, 110, 117, 108, 108, 9, 108, 100, 99, 46, 105, 52, 46, 109, 49, 8, 108, 100, 99, 46, 105, 52, 46, 48, 8, 108, 100, 99, 46, 105, 52, 46, 49, 8, 108, 100, 99, 46, 105, 52, 46, 50, 8, 108, 100, 99, 46, 105, 52, 46, 51, 8, 108, 100, 99, 46, 105, 52, 46, 52, 8, 108, 100, 99, 46, 105, 52, 46, 53, 8, 108, 100, 99, 46, 105, 52, 46, 54, 8, 108, 100, 99, 46, 105, 52, 46, 55, 8, 108, 100, 99, 46, 105, 52, 46, 56, 8, 108, 100, 99, 46, 105, 52, 46, 115, 6, 108, 100, 99, 46, 105, 52, 6, 108, 100, 99, 46, 105, 56, 6, 108, 100, 99, 46, 114, 52, 6, 108, 100, 99, 46, 114, 56, 3, 100, 117, 112, 3, 112, 111, 112, 3, 106, 109, 112, 4, 99, 97, 108, 108, 5, 99, 97, 108, 108, 105, 3, 114, 101, 116, 4, 98, 114, 46, 115, 9, 98, 114, 102, 97, 108, 115, 101, 46, 115, 8, 98, 114, 116, 114, 117, 101, 46, 115, 5, 98, 101, 113, 46, 115, 5, 98, 103, 101, 46, 115, 5, 98, 103, 116, 46, 115, 5, 98, 108, 101, 46, 115, 5, 98, 108, 116, 46, 115, 8, 98, 110, 101, 46, 117, 110, 46, 115, 8, 98, 103, 101, 46, 117, 110, 46, 115, 8, 98, 103, 116, 46, 117, 110, 46, 115, 8, 98, 108, 101, 46, 117, 110, 46, 115, 8, 98, 108, 116, 46, 117, 110, 46, 115, 2, 98, 114, 7, 98, 114, 102, 97, 108, 115, 101, 6, 98, 114, 116, 114, 117, 101, 3, 98, 101, 113, 3, 98, 103, 101, 3, 98, 103, 116, 3, 98, 108, 101, 3, 98, 108, 116, 6, 98, 110, 101, 46, 117, 110, 6, 98, 103, 101, 46, 117, 110, 6, 98, 103, 116, 46, 117, 110, 6, 98, 108, 101, 46, 117, 110, 6, 98, 108, 116, 46, 117, 110, 6, 115, 119, 105, 116, 99, 104, 8, 108, 100, 105, 110, 100, 46, 105, 49, 8, 108, 100, 105, 110, 100, 46, 117, 49, 8, 108, 100, 105, 110, 100, 46, 105, 50, 8, 108, 100, 105, 110, 100, 46, 117, 50, 8, 108, 100, 105, 110, 100, 46, 105, 52, 8, 108, 100, 105, 110, 100, 46, 117, 52, 8, 108, 100, 105, 110, 100, 46, 105, 56, 7, 108, 100, 105, 110, 100, 46, 105, 8, 108, 100, 105, 110, 100, 46, 114, 52, 8, 108, 100, 105, 110, 100, 46, 114, 56, 9, 108, 100, 105, 110, 100, 46, 114, 101, 102, 9, 115, 116, 105, 110, 100, 46, 114, 101, 102, 8, 115, 116, 105, 110, 100, 46, 105, 49, 8, 115, 116, 105, 110, 100, 46, 105, 50, 8, 115, 116, 105, 110, 100, 46, 105, 52, 8, 115, 116, 105, 110, 100, 46, 105, 56, 8, 115, 116, 105, 110, 100, 46, 114, 52, 8, 115, 116, 105, 110, 100, 46, 114, 56, 3, 97, 100, 100, 3, 115, 117, 98, 3, 109, 117, 108, 3, 100, 105, 118, 6, 100, 105, 118, 46, 117, 110, 3, 114, 101, 109, 6, 114, 101, 109, 46, 117, 110, 3, 97, 110, 100, 2, 111, 114, 3, 120, 111, 114, 3, 115, 104, 108, 3, 115, 104, 114, 6, 115, 104, 114, 46, 117, 110, 3, 110, 101, 103, 3, 110, 111, 116, 7, 99, 111, 110, 118, 46, 105, 49, 7, 99, 111, 110, 118, 46, 105, 50, 7, 99, 111, 110, 118, 46, 105, 52, 7, 99, 111, 110, 118, 46, 105, 56, 7, 99, 111, 110, 118, 46, 114, 52, 7, 99, 111, 110, 118, 46, 114, 56, 7, 99, 111, 110, 118, 46, 117, 52, 7, 99, 111, 110, 118, 46, 117, 56, 8, 99, 97, 108, 108, 118, 105, 114, 116, 5, 99, 112, 111, 98, 106, 5, 108, 100, 111, 98, 106, 5, 108, 100, 115, 116, 114, 6, 110, 101, 119, 111, 98, 106, 9, 99, 97, 115, 116, 99, 108, 97, 115, 115, 6, 105, 115, 105, 110, 115, 116, 9, 99, 111, 110, 118, 46, 114, 46, 117, 110, 5, 117, 110, 98, 111, 120, 5, 116, 104, 114, 111, 119, 5, 108, 100, 102, 108, 100, 6, 108, 100, 102, 108, 100, 97, 5, 115, 116, 102, 108, 100, 6, 108, 100, 115, 102, 108, 100, 7, 108, 100, 115, 102, 108, 100, 97, 6, 115, 116, 115, 102, 108, 100, 5, 115, 116, 111, 98, 106, 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 49, 46, 117, 110, 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 50, 46, 117, 110, 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 52, 46, 117, 110, 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 56, 46, 117, 110, 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 49, 46, 117, 110, 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 50, 46, 117, 110, 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 52, 46, 117, 110, 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 56, 46, 117, 110, 13, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 46, 117, 110, 13, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 46, 117, 110, 3, 98, 111, 120, 6, 110, 101, 119, 97, 114, 114, 5, 108, 100, 108, 101, 110, 7, 108, 100, 101, 108, 101, 109, 97, 9, 108, 100, 101, 108, 101, 109, 46, 105, 49, 9, 108, 100, 101, 108, 101, 109, 46, 117, 49, 9, 108, 100, 101, 108, 101, 109, 46, 105, 50, 9, 108, 100, 101, 108, 101, 109, 46, 117, 50, 9, 108, 100, 101, 108, 101, 109, 46, 105, 52, 9, 108, 100, 101, 108, 101, 109, 46, 117, 52, 9, 108, 100, 101, 108, 101, 109, 46, 105, 56, 8, 108, 100, 101, 108, 101, 109, 46, 105, 9, 108, 100, 101, 108, 101, 109, 46, 114, 52, 9, 108, 100, 101, 108, 101, 109, 46, 114, 56, 10, 108, 100, 101, 108, 101, 109, 46, 114, 101, 102, 8, 115, 116, 101, 108, 101, 109, 46, 105, 9, 115, 116, 101, 108, 101, 109, 46, 105, 49, 9, 115, 116, 101, 108, 101, 109, 46, 105, 50, 9, 115, 116, 101, 108, 101, 109, 46, 105, 52, 9, 115, 116, 101, 108, 101, 109, 46, 105, 56, 9, 115, 116, 101, 108, 101, 109, 46, 114, 52, 9, 115, 116, 101, 108, 101, 109, 46, 114, 56, 10, 115, 116, 101, 108, 101, 109, 46, 114, 101, 102, 10, 108, 100, 101, 108, 101, 109, 46, 97, 110, 121, 10, 115, 116, 101, 108, 101, 109, 46, 97, 110, 121, 9, 117, 110, 98, 111, 120, 46, 97, 110, 121, 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 49, 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 49, 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 50, 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 50, 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 52, 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 52, 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 56, 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 56, 9, 114, 101, 102, 97, 110, 121, 118, 97, 108, 8, 99, 107, 102, 105, 110, 105, 116, 101, 8, 109, 107, 114, 101, 102, 97, 110, 121, 7, 108, 100, 116, 111, 107, 101, 110, 7, 99, 111, 110, 118, 46, 117, 50, 7, 99, 111, 110, 118, 46, 117, 49, 6, 99, 111, 110, 118, 46, 105, 10, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 10, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 7, 97, 100, 100, 46, 111, 118, 102, 10, 97, 100, 100, 46, 111, 118, 102, 46, 117, 110, 7, 109, 117, 108, 46, 111, 118, 102, 10, 109, 117, 108, 46, 111, 118, 102, 46, 117, 110, 7, 115, 117, 98, 46, 111, 118, 102, 10, 115, 117, 98, 46, 111, 118, 102, 46, 117, 110, 10, 101, 110, 100, 102, 105, 110, 97, 108, 108, 121, 5, 108, 101, 97, 118, 101, 7, 108, 101, 97, 118, 101, 46, 115, 7, 115, 116, 105, 110, 100, 46, 105, 6, 99, 111, 110, 118, 46, 117, 7, 97, 114, 103, 108, 105, 115, 116, 3, 99, 101, 113, 3, 99, 103, 116, 6, 99, 103, 116, 46, 117, 110, 3, 99, 108, 116, 6, 99, 108, 116, 46, 117, 110, 5, 108, 100, 102, 116, 110, 9, 108, 100, 118, 105, 114, 116, 102, 116, 110, 5, 108, 100, 97, 114, 103, 6, 108, 100, 97, 114, 103, 97, 5, 115, 116, 97, 114, 103, 5, 108, 100, 108, 111, 99, 6, 108, 100, 108, 111, 99, 97, 5, 115, 116, 108, 111, 99, 8, 108, 111, 99, 97, 108, 108, 111, 99, 9, 101, 110, 100, 102, 105, 108, 116, 101, 114, 10, 117, 110, 97, 108, 105, 103, 110, 101, 100, 46, 9, 118, 111, 108, 97, 116, 105, 108, 101, 46, 5, 116, 97, 105, 108, 46, 7, 105, 110, 105, 116, 111, 98, 106, 12, 99, 111, 110, 115, 116, 114, 97, 105, 110, 101, 100, 46, 5, 99, 112, 98, 108, 107, 7, 105, 110, 105, 116, 98, 108, 107, 3, 110, 111, 46, 7, 114, 101, 116, 104, 114, 111, 119, 6, 115, 105, 122, 101, 111, 102, 10, 114, 101, 102, 97, 110, 121, 116, 121, 112, 101, 9, 114, 101, 97, 100, 111, 110, 108, 121, 46, }; names = new string [219]; for (int i = 0, p = 0; i < names.Length; i++) { var buffer = new char [table [p++]]; for (int j = 0; j < buffer.Length; j++) buffer [j] = (char) table [p++]; names [i] = new string (buffer); } } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/OpCodes.cs ================================================ // // OpCodes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil.Cil { public static class OpCodes { internal static readonly OpCode [] OneByteOpCode = new OpCode [0xe0 + 1]; internal static readonly OpCode [] TwoBytesOpCode = new OpCode [0x1e + 1]; public static readonly OpCode Nop = new OpCode ( 0xff << 0 | 0x00 << 8 | (byte) Code.Nop << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Break = new OpCode ( 0xff << 0 | 0x01 << 8 | (byte) Code.Break << 16 | (byte) FlowControl.Break << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldarg_0 = new OpCode ( 0xff << 0 | 0x02 << 8 | (byte) Code.Ldarg_0 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldarg_1 = new OpCode ( 0xff << 0 | 0x03 << 8 | (byte) Code.Ldarg_1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldarg_2 = new OpCode ( 0xff << 0 | 0x04 << 8 | (byte) Code.Ldarg_2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldarg_3 = new OpCode ( 0xff << 0 | 0x05 << 8 | (byte) Code.Ldarg_3 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldloc_0 = new OpCode ( 0xff << 0 | 0x06 << 8 | (byte) Code.Ldloc_0 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldloc_1 = new OpCode ( 0xff << 0 | 0x07 << 8 | (byte) Code.Ldloc_1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldloc_2 = new OpCode ( 0xff << 0 | 0x08 << 8 | (byte) Code.Ldloc_2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldloc_3 = new OpCode ( 0xff << 0 | 0x09 << 8 | (byte) Code.Ldloc_3 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Stloc_0 = new OpCode ( 0xff << 0 | 0x0a << 8 | (byte) Code.Stloc_0 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stloc_1 = new OpCode ( 0xff << 0 | 0x0b << 8 | (byte) Code.Stloc_1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stloc_2 = new OpCode ( 0xff << 0 | 0x0c << 8 | (byte) Code.Stloc_2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stloc_3 = new OpCode ( 0xff << 0 | 0x0d << 8 | (byte) Code.Stloc_3 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldarg_S = new OpCode ( 0xff << 0 | 0x0e << 8 | (byte) Code.Ldarg_S << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineArg << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldarga_S = new OpCode ( 0xff << 0 | 0x0f << 8 | (byte) Code.Ldarga_S << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineArg << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Starg_S = new OpCode ( 0xff << 0 | 0x10 << 8 | (byte) Code.Starg_S << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineArg << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldloc_S = new OpCode ( 0xff << 0 | 0x11 << 8 | (byte) Code.Ldloc_S << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineVar << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldloca_S = new OpCode ( 0xff << 0 | 0x12 << 8 | (byte) Code.Ldloca_S << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineVar << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Stloc_S = new OpCode ( 0xff << 0 | 0x13 << 8 | (byte) Code.Stloc_S << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineVar << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldnull = new OpCode ( 0xff << 0 | 0x14 << 8 | (byte) Code.Ldnull << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushref << 24); public static readonly OpCode Ldc_I4_M1 = new OpCode ( 0xff << 0 | 0x15 << 8 | (byte) Code.Ldc_I4_M1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_0 = new OpCode ( 0xff << 0 | 0x16 << 8 | (byte) Code.Ldc_I4_0 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_1 = new OpCode ( 0xff << 0 | 0x17 << 8 | (byte) Code.Ldc_I4_1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_2 = new OpCode ( 0xff << 0 | 0x18 << 8 | (byte) Code.Ldc_I4_2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_3 = new OpCode ( 0xff << 0 | 0x19 << 8 | (byte) Code.Ldc_I4_3 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_4 = new OpCode ( 0xff << 0 | 0x1a << 8 | (byte) Code.Ldc_I4_4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_5 = new OpCode ( 0xff << 0 | 0x1b << 8 | (byte) Code.Ldc_I4_5 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_6 = new OpCode ( 0xff << 0 | 0x1c << 8 | (byte) Code.Ldc_I4_6 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_7 = new OpCode ( 0xff << 0 | 0x1d << 8 | (byte) Code.Ldc_I4_7 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_8 = new OpCode ( 0xff << 0 | 0x1e << 8 | (byte) Code.Ldc_I4_8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_S = new OpCode ( 0xff << 0 | 0x1f << 8 | (byte) Code.Ldc_I4_S << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineI << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4 = new OpCode ( 0xff << 0 | 0x20 << 8 | (byte) Code.Ldc_I4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineI << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I8 = new OpCode ( 0xff << 0 | 0x21 << 8 | (byte) Code.Ldc_I8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineI8 << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi8 << 24); public static readonly OpCode Ldc_R4 = new OpCode ( 0xff << 0 | 0x22 << 8 | (byte) Code.Ldc_R4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.ShortInlineR << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushr4 << 24); public static readonly OpCode Ldc_R8 = new OpCode ( 0xff << 0 | 0x23 << 8 | (byte) Code.Ldc_R8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineR << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushr8 << 24); public static readonly OpCode Dup = new OpCode ( 0xff << 0 | 0x25 << 8 | (byte) Code.Dup << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push1_push1 << 24); public static readonly OpCode Pop = new OpCode ( 0xff << 0 | 0x26 << 8 | (byte) Code.Pop << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Jmp = new OpCode ( 0xff << 0 | 0x27 << 8 | (byte) Code.Jmp << 16 | (byte) FlowControl.Call << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Call = new OpCode ( 0xff << 0 | 0x28 << 8 | (byte) Code.Call << 16 | (byte) FlowControl.Call << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Varpush << 24); public static readonly OpCode Calli = new OpCode ( 0xff << 0 | 0x29 << 8 | (byte) Code.Calli << 16 | (byte) FlowControl.Call << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineSig << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Varpush << 24); public static readonly OpCode Ret = new OpCode ( 0xff << 0 | 0x2a << 8 | (byte) Code.Ret << 16 | (byte) FlowControl.Return << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Br_S = new OpCode ( 0xff << 0 | 0x2b << 8 | (byte) Code.Br_S << 16 | (byte) FlowControl.Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Brfalse_S = new OpCode ( 0xff << 0 | 0x2c << 8 | (byte) Code.Brfalse_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Brtrue_S = new OpCode ( 0xff << 0 | 0x2d << 8 | (byte) Code.Brtrue_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Beq_S = new OpCode ( 0xff << 0 | 0x2e << 8 | (byte) Code.Beq_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bge_S = new OpCode ( 0xff << 0 | 0x2f << 8 | (byte) Code.Bge_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bgt_S = new OpCode ( 0xff << 0 | 0x30 << 8 | (byte) Code.Bgt_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ble_S = new OpCode ( 0xff << 0 | 0x31 << 8 | (byte) Code.Ble_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Blt_S = new OpCode ( 0xff << 0 | 0x32 << 8 | (byte) Code.Blt_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bne_Un_S = new OpCode ( 0xff << 0 | 0x33 << 8 | (byte) Code.Bne_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bge_Un_S = new OpCode ( 0xff << 0 | 0x34 << 8 | (byte) Code.Bge_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bgt_Un_S = new OpCode ( 0xff << 0 | 0x35 << 8 | (byte) Code.Bgt_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ble_Un_S = new OpCode ( 0xff << 0 | 0x36 << 8 | (byte) Code.Ble_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Blt_Un_S = new OpCode ( 0xff << 0 | 0x37 << 8 | (byte) Code.Blt_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Br = new OpCode ( 0xff << 0 | 0x38 << 8 | (byte) Code.Br << 16 | (byte) FlowControl.Branch << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Brfalse = new OpCode ( 0xff << 0 | 0x39 << 8 | (byte) Code.Brfalse << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Brtrue = new OpCode ( 0xff << 0 | 0x3a << 8 | (byte) Code.Brtrue << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Beq = new OpCode ( 0xff << 0 | 0x3b << 8 | (byte) Code.Beq << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bge = new OpCode ( 0xff << 0 | 0x3c << 8 | (byte) Code.Bge << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bgt = new OpCode ( 0xff << 0 | 0x3d << 8 | (byte) Code.Bgt << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ble = new OpCode ( 0xff << 0 | 0x3e << 8 | (byte) Code.Ble << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Blt = new OpCode ( 0xff << 0 | 0x3f << 8 | (byte) Code.Blt << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bne_Un = new OpCode ( 0xff << 0 | 0x40 << 8 | (byte) Code.Bne_Un << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bge_Un = new OpCode ( 0xff << 0 | 0x41 << 8 | (byte) Code.Bge_Un << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bgt_Un = new OpCode ( 0xff << 0 | 0x42 << 8 | (byte) Code.Bgt_Un << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ble_Un = new OpCode ( 0xff << 0 | 0x43 << 8 | (byte) Code.Ble_Un << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Blt_Un = new OpCode ( 0xff << 0 | 0x44 << 8 | (byte) Code.Blt_Un << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Switch = new OpCode ( 0xff << 0 | 0x45 << 8 | (byte) Code.Switch << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineSwitch << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldind_I1 = new OpCode ( 0xff << 0 | 0x46 << 8 | (byte) Code.Ldind_I1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldind_U1 = new OpCode ( 0xff << 0 | 0x47 << 8 | (byte) Code.Ldind_U1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldind_I2 = new OpCode ( 0xff << 0 | 0x48 << 8 | (byte) Code.Ldind_I2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldind_U2 = new OpCode ( 0xff << 0 | 0x49 << 8 | (byte) Code.Ldind_U2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldind_I4 = new OpCode ( 0xff << 0 | 0x4a << 8 | (byte) Code.Ldind_I4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldind_U4 = new OpCode ( 0xff << 0 | 0x4b << 8 | (byte) Code.Ldind_U4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldind_I8 = new OpCode ( 0xff << 0 | 0x4c << 8 | (byte) Code.Ldind_I8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi8 << 24); public static readonly OpCode Ldind_I = new OpCode ( 0xff << 0 | 0x4d << 8 | (byte) Code.Ldind_I << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldind_R4 = new OpCode ( 0xff << 0 | 0x4e << 8 | (byte) Code.Ldind_R4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushr4 << 24); public static readonly OpCode Ldind_R8 = new OpCode ( 0xff << 0 | 0x4f << 8 | (byte) Code.Ldind_R8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushr8 << 24); public static readonly OpCode Ldind_Ref = new OpCode ( 0xff << 0 | 0x50 << 8 | (byte) Code.Ldind_Ref << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushref << 24); public static readonly OpCode Stind_Ref = new OpCode ( 0xff << 0 | 0x51 << 8 | (byte) Code.Stind_Ref << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stind_I1 = new OpCode ( 0xff << 0 | 0x52 << 8 | (byte) Code.Stind_I1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stind_I2 = new OpCode ( 0xff << 0 | 0x53 << 8 | (byte) Code.Stind_I2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stind_I4 = new OpCode ( 0xff << 0 | 0x54 << 8 | (byte) Code.Stind_I4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stind_I8 = new OpCode ( 0xff << 0 | 0x55 << 8 | (byte) Code.Stind_I8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi8 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stind_R4 = new OpCode ( 0xff << 0 | 0x56 << 8 | (byte) Code.Stind_R4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popr4 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stind_R8 = new OpCode ( 0xff << 0 | 0x57 << 8 | (byte) Code.Stind_R8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popr8 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Add = new OpCode ( 0xff << 0 | 0x58 << 8 | (byte) Code.Add << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Sub = new OpCode ( 0xff << 0 | 0x59 << 8 | (byte) Code.Sub << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Mul = new OpCode ( 0xff << 0 | 0x5a << 8 | (byte) Code.Mul << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Div = new OpCode ( 0xff << 0 | 0x5b << 8 | (byte) Code.Div << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Div_Un = new OpCode ( 0xff << 0 | 0x5c << 8 | (byte) Code.Div_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Rem = new OpCode ( 0xff << 0 | 0x5d << 8 | (byte) Code.Rem << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Rem_Un = new OpCode ( 0xff << 0 | 0x5e << 8 | (byte) Code.Rem_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode And = new OpCode ( 0xff << 0 | 0x5f << 8 | (byte) Code.And << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Or = new OpCode ( 0xff << 0 | 0x60 << 8 | (byte) Code.Or << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Xor = new OpCode ( 0xff << 0 | 0x61 << 8 | (byte) Code.Xor << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Shl = new OpCode ( 0xff << 0 | 0x62 << 8 | (byte) Code.Shl << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Shr = new OpCode ( 0xff << 0 | 0x63 << 8 | (byte) Code.Shr << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Shr_Un = new OpCode ( 0xff << 0 | 0x64 << 8 | (byte) Code.Shr_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Neg = new OpCode ( 0xff << 0 | 0x65 << 8 | (byte) Code.Neg << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Not = new OpCode ( 0xff << 0 | 0x66 << 8 | (byte) Code.Not << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Conv_I1 = new OpCode ( 0xff << 0 | 0x67 << 8 | (byte) Code.Conv_I1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_I2 = new OpCode ( 0xff << 0 | 0x68 << 8 | (byte) Code.Conv_I2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_I4 = new OpCode ( 0xff << 0 | 0x69 << 8 | (byte) Code.Conv_I4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_I8 = new OpCode ( 0xff << 0 | 0x6a << 8 | (byte) Code.Conv_I8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24); public static readonly OpCode Conv_R4 = new OpCode ( 0xff << 0 | 0x6b << 8 | (byte) Code.Conv_R4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushr4 << 24); public static readonly OpCode Conv_R8 = new OpCode ( 0xff << 0 | 0x6c << 8 | (byte) Code.Conv_R8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushr8 << 24); public static readonly OpCode Conv_U4 = new OpCode ( 0xff << 0 | 0x6d << 8 | (byte) Code.Conv_U4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_U8 = new OpCode ( 0xff << 0 | 0x6e << 8 | (byte) Code.Conv_U8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24); public static readonly OpCode Callvirt = new OpCode ( 0xff << 0 | 0x6f << 8 | (byte) Code.Callvirt << 16 | (byte) FlowControl.Call << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Varpush << 24); public static readonly OpCode Cpobj = new OpCode ( 0xff << 0 | 0x70 << 8 | (byte) Code.Cpobj << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldobj = new OpCode ( 0xff << 0 | 0x71 << 8 | (byte) Code.Ldobj << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldstr = new OpCode ( 0xff << 0 | 0x72 << 8 | (byte) Code.Ldstr << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineString << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushref << 24); public static readonly OpCode Newobj = new OpCode ( 0xff << 0 | 0x73 << 8 | (byte) Code.Newobj << 16 | (byte) FlowControl.Call << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Pushref << 24); public static readonly OpCode Castclass = new OpCode ( 0xff << 0 | 0x74 << 8 | (byte) Code.Castclass << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushref << 24); public static readonly OpCode Isinst = new OpCode ( 0xff << 0 | 0x75 << 8 | (byte) Code.Isinst << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_R_Un = new OpCode ( 0xff << 0 | 0x76 << 8 | (byte) Code.Conv_R_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushr8 << 24); public static readonly OpCode Unbox = new OpCode ( 0xff << 0 | 0x79 << 8 | (byte) Code.Unbox << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Throw = new OpCode ( 0xff << 0 | 0x7a << 8 | (byte) Code.Throw << 16 | (byte) FlowControl.Throw << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldfld = new OpCode ( 0xff << 0 | 0x7b << 8 | (byte) Code.Ldfld << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldflda = new OpCode ( 0xff << 0 | 0x7c << 8 | (byte) Code.Ldflda << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Stfld = new OpCode ( 0xff << 0 | 0x7d << 8 | (byte) Code.Stfld << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Popref_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldsfld = new OpCode ( 0xff << 0 | 0x7e << 8 | (byte) Code.Ldsfld << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldsflda = new OpCode ( 0xff << 0 | 0x7f << 8 | (byte) Code.Ldsflda << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Stsfld = new OpCode ( 0xff << 0 | 0x80 << 8 | (byte) Code.Stsfld << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stobj = new OpCode ( 0xff << 0 | 0x81 << 8 | (byte) Code.Stobj << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Conv_Ovf_I1_Un = new OpCode ( 0xff << 0 | 0x82 << 8 | (byte) Code.Conv_Ovf_I1_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_I2_Un = new OpCode ( 0xff << 0 | 0x83 << 8 | (byte) Code.Conv_Ovf_I2_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_I4_Un = new OpCode ( 0xff << 0 | 0x84 << 8 | (byte) Code.Conv_Ovf_I4_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_I8_Un = new OpCode ( 0xff << 0 | 0x85 << 8 | (byte) Code.Conv_Ovf_I8_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24); public static readonly OpCode Conv_Ovf_U1_Un = new OpCode ( 0xff << 0 | 0x86 << 8 | (byte) Code.Conv_Ovf_U1_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_U2_Un = new OpCode ( 0xff << 0 | 0x87 << 8 | (byte) Code.Conv_Ovf_U2_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_U4_Un = new OpCode ( 0xff << 0 | 0x88 << 8 | (byte) Code.Conv_Ovf_U4_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_U8_Un = new OpCode ( 0xff << 0 | 0x89 << 8 | (byte) Code.Conv_Ovf_U8_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24); public static readonly OpCode Conv_Ovf_I_Un = new OpCode ( 0xff << 0 | 0x8a << 8 | (byte) Code.Conv_Ovf_I_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_U_Un = new OpCode ( 0xff << 0 | 0x8b << 8 | (byte) Code.Conv_Ovf_U_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Box = new OpCode ( 0xff << 0 | 0x8c << 8 | (byte) Code.Box << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushref << 24); public static readonly OpCode Newarr = new OpCode ( 0xff << 0 | 0x8d << 8 | (byte) Code.Newarr << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushref << 24); public static readonly OpCode Ldlen = new OpCode ( 0xff << 0 | 0x8e << 8 | (byte) Code.Ldlen << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldelema = new OpCode ( 0xff << 0 | 0x8f << 8 | (byte) Code.Ldelema << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldelem_I1 = new OpCode ( 0xff << 0 | 0x90 << 8 | (byte) Code.Ldelem_I1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldelem_U1 = new OpCode ( 0xff << 0 | 0x91 << 8 | (byte) Code.Ldelem_U1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldelem_I2 = new OpCode ( 0xff << 0 | 0x92 << 8 | (byte) Code.Ldelem_I2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldelem_U2 = new OpCode ( 0xff << 0 | 0x93 << 8 | (byte) Code.Ldelem_U2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldelem_I4 = new OpCode ( 0xff << 0 | 0x94 << 8 | (byte) Code.Ldelem_I4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldelem_U4 = new OpCode ( 0xff << 0 | 0x95 << 8 | (byte) Code.Ldelem_U4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldelem_I8 = new OpCode ( 0xff << 0 | 0x96 << 8 | (byte) Code.Ldelem_I8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi8 << 24); public static readonly OpCode Ldelem_I = new OpCode ( 0xff << 0 | 0x97 << 8 | (byte) Code.Ldelem_I << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldelem_R4 = new OpCode ( 0xff << 0 | 0x98 << 8 | (byte) Code.Ldelem_R4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushr4 << 24); public static readonly OpCode Ldelem_R8 = new OpCode ( 0xff << 0 | 0x99 << 8 | (byte) Code.Ldelem_R8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushr8 << 24); public static readonly OpCode Ldelem_Ref = new OpCode ( 0xff << 0 | 0x9a << 8 | (byte) Code.Ldelem_Ref << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushref << 24); public static readonly OpCode Stelem_I = new OpCode ( 0xff << 0 | 0x9b << 8 | (byte) Code.Stelem_I << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stelem_I1 = new OpCode ( 0xff << 0 | 0x9c << 8 | (byte) Code.Stelem_I1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stelem_I2 = new OpCode ( 0xff << 0 | 0x9d << 8 | (byte) Code.Stelem_I2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stelem_I4 = new OpCode ( 0xff << 0 | 0x9e << 8 | (byte) Code.Stelem_I4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stelem_I8 = new OpCode ( 0xff << 0 | 0x9f << 8 | (byte) Code.Stelem_I8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi8 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stelem_R4 = new OpCode ( 0xff << 0 | 0xa0 << 8 | (byte) Code.Stelem_R4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popr4 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stelem_R8 = new OpCode ( 0xff << 0 | 0xa1 << 8 | (byte) Code.Stelem_R8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popr8 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stelem_Ref = new OpCode ( 0xff << 0 | 0xa2 << 8 | (byte) Code.Stelem_Ref << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popref << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldelem_Any = new OpCode ( 0xff << 0 | 0xa3 << 8 | (byte) Code.Ldelem_Any << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Stelem_Any = new OpCode ( 0xff << 0 | 0xa4 << 8 | (byte) Code.Stelem_Any << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref_popi_popref << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Unbox_Any = new OpCode ( 0xff << 0 | 0xa5 << 8 | (byte) Code.Unbox_Any << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Conv_Ovf_I1 = new OpCode ( 0xff << 0 | 0xb3 << 8 | (byte) Code.Conv_Ovf_I1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_U1 = new OpCode ( 0xff << 0 | 0xb4 << 8 | (byte) Code.Conv_Ovf_U1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_I2 = new OpCode ( 0xff << 0 | 0xb5 << 8 | (byte) Code.Conv_Ovf_I2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_U2 = new OpCode ( 0xff << 0 | 0xb6 << 8 | (byte) Code.Conv_Ovf_U2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_I4 = new OpCode ( 0xff << 0 | 0xb7 << 8 | (byte) Code.Conv_Ovf_I4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_U4 = new OpCode ( 0xff << 0 | 0xb8 << 8 | (byte) Code.Conv_Ovf_U4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_I8 = new OpCode ( 0xff << 0 | 0xb9 << 8 | (byte) Code.Conv_Ovf_I8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24); public static readonly OpCode Conv_Ovf_U8 = new OpCode ( 0xff << 0 | 0xba << 8 | (byte) Code.Conv_Ovf_U8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24); public static readonly OpCode Refanyval = new OpCode ( 0xff << 0 | 0xc2 << 8 | (byte) Code.Refanyval << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ckfinite = new OpCode ( 0xff << 0 | 0xc3 << 8 | (byte) Code.Ckfinite << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushr8 << 24); public static readonly OpCode Mkrefany = new OpCode ( 0xff << 0 | 0xc6 << 8 | (byte) Code.Mkrefany << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldtoken = new OpCode ( 0xff << 0 | 0xd0 << 8 | (byte) Code.Ldtoken << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineTok << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_U2 = new OpCode ( 0xff << 0 | 0xd1 << 8 | (byte) Code.Conv_U2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_U1 = new OpCode ( 0xff << 0 | 0xd2 << 8 | (byte) Code.Conv_U1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_I = new OpCode ( 0xff << 0 | 0xd3 << 8 | (byte) Code.Conv_I << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_I = new OpCode ( 0xff << 0 | 0xd4 << 8 | (byte) Code.Conv_Ovf_I << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_U = new OpCode ( 0xff << 0 | 0xd5 << 8 | (byte) Code.Conv_Ovf_U << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Add_Ovf = new OpCode ( 0xff << 0 | 0xd6 << 8 | (byte) Code.Add_Ovf << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Add_Ovf_Un = new OpCode ( 0xff << 0 | 0xd7 << 8 | (byte) Code.Add_Ovf_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Mul_Ovf = new OpCode ( 0xff << 0 | 0xd8 << 8 | (byte) Code.Mul_Ovf << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Mul_Ovf_Un = new OpCode ( 0xff << 0 | 0xd9 << 8 | (byte) Code.Mul_Ovf_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Sub_Ovf = new OpCode ( 0xff << 0 | 0xda << 8 | (byte) Code.Sub_Ovf << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Sub_Ovf_Un = new OpCode ( 0xff << 0 | 0xdb << 8 | (byte) Code.Sub_Ovf_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Endfinally = new OpCode ( 0xff << 0 | 0xdc << 8 | (byte) Code.Endfinally << 16 | (byte) FlowControl.Return << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Leave = new OpCode ( 0xff << 0 | 0xdd << 8 | (byte) Code.Leave << 16 | (byte) FlowControl.Branch << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.PopAll << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Leave_S = new OpCode ( 0xff << 0 | 0xde << 8 | (byte) Code.Leave_S << 16 | (byte) FlowControl.Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.PopAll << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stind_I = new OpCode ( 0xff << 0 | 0xdf << 8 | (byte) Code.Stind_I << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Conv_U = new OpCode ( 0xff << 0 | 0xe0 << 8 | (byte) Code.Conv_U << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Arglist = new OpCode ( 0xfe << 0 | 0x00 << 8 | (byte) Code.Arglist << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ceq = new OpCode ( 0xfe << 0 | 0x01 << 8 | (byte) Code.Ceq << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Cgt = new OpCode ( 0xfe << 0 | 0x02 << 8 | (byte) Code.Cgt << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Cgt_Un = new OpCode ( 0xfe << 0 | 0x03 << 8 | (byte) Code.Cgt_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Clt = new OpCode ( 0xfe << 0 | 0x04 << 8 | (byte) Code.Clt << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Clt_Un = new OpCode ( 0xfe << 0 | 0x05 << 8 | (byte) Code.Clt_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldftn = new OpCode ( 0xfe << 0 | 0x06 << 8 | (byte) Code.Ldftn << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldvirtftn = new OpCode ( 0xfe << 0 | 0x07 << 8 | (byte) Code.Ldvirtftn << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldarg = new OpCode ( 0xfe << 0 | 0x09 << 8 | (byte) Code.Ldarg << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineArg << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldarga = new OpCode ( 0xfe << 0 | 0x0a << 8 | (byte) Code.Ldarga << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineArg << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Starg = new OpCode ( 0xfe << 0 | 0x0b << 8 | (byte) Code.Starg << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineArg << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldloc = new OpCode ( 0xfe << 0 | 0x0c << 8 | (byte) Code.Ldloc << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineVar << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldloca = new OpCode ( 0xfe << 0 | 0x0d << 8 | (byte) Code.Ldloca << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineVar << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Stloc = new OpCode ( 0xfe << 0 | 0x0e << 8 | (byte) Code.Stloc << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineVar << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Localloc = new OpCode ( 0xfe << 0 | 0x0f << 8 | (byte) Code.Localloc << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Endfilter = new OpCode ( 0xfe << 0 | 0x11 << 8 | (byte) Code.Endfilter << 16 | (byte) FlowControl.Return << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Unaligned = new OpCode ( 0xfe << 0 | 0x12 << 8 | (byte) Code.Unaligned << 16 | (byte) FlowControl.Meta << 24, (byte) OpCodeType.Prefix << 0 | (byte) OperandType.ShortInlineI << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Volatile = new OpCode ( 0xfe << 0 | 0x13 << 8 | (byte) Code.Volatile << 16 | (byte) FlowControl.Meta << 24, (byte) OpCodeType.Prefix << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Tail = new OpCode ( 0xfe << 0 | 0x14 << 8 | (byte) Code.Tail << 16 | (byte) FlowControl.Meta << 24, (byte) OpCodeType.Prefix << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Initobj = new OpCode ( 0xfe << 0 | 0x15 << 8 | (byte) Code.Initobj << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Constrained = new OpCode ( 0xfe << 0 | 0x16 << 8 | (byte) Code.Constrained << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Prefix << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Cpblk = new OpCode ( 0xfe << 0 | 0x17 << 8 | (byte) Code.Cpblk << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Initblk = new OpCode ( 0xfe << 0 | 0x18 << 8 | (byte) Code.Initblk << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode No = new OpCode ( 0xfe << 0 | 0x19 << 8 | (byte) Code.No << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Prefix << 0 | (byte) OperandType.ShortInlineI << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Rethrow = new OpCode ( 0xfe << 0 | 0x1a << 8 | (byte) Code.Rethrow << 16 | (byte) FlowControl.Throw << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Sizeof = new OpCode ( 0xfe << 0 | 0x1c << 8 | (byte) Code.Sizeof << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Refanytype = new OpCode ( 0xfe << 0 | 0x1d << 8 | (byte) Code.Refanytype << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Readonly = new OpCode ( 0xfe << 0 | 0x1e << 8 | (byte) Code.Readonly << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Prefix << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/SequencePoint.cs ================================================ // // SequencePoint.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil.Cil { public sealed class SequencePoint { Document document; int start_line; int start_column; int end_line; int end_column; public int StartLine { get { return start_line; } set { start_line = value; } } public int StartColumn { get { return start_column; } set { start_column = value; } } public int EndLine { get { return end_line; } set { end_line = value; } } public int EndColumn { get { return end_column; } set { end_column = value; } } public Document Document { get { return document; } set { document = value; } } public SequencePoint (Document document) { this.document = document; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/Symbols.cs ================================================ // // Symbols.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.IO; using System.Runtime.InteropServices; using SR = System.Reflection; using Mono.Collections.Generic; namespace Mono.Cecil.Cil { [StructLayout (LayoutKind.Sequential)] public struct ImageDebugDirectory { public int Characteristics; public int TimeDateStamp; public short MajorVersion; public short MinorVersion; public int Type; public int SizeOfData; public int AddressOfRawData; public int PointerToRawData; } public sealed class Scope : IVariableDefinitionProvider { Instruction start; Instruction end; Collection scopes; Collection variables; public Instruction Start { get { return start; } set { start = value; } } public Instruction End { get { return end; } set { end = value; } } public bool HasScopes { get { return !Mixin.IsNullOrEmpty (scopes); } } public Collection Scopes { get { if (scopes == null) scopes = new Collection (); return scopes; } } public bool HasVariables { get { return !Mixin.IsNullOrEmpty (variables); } } public Collection Variables { get { if (variables == null) variables = new Collection (); return variables; } } } public struct InstructionSymbol { public readonly int Offset; public readonly SequencePoint SequencePoint; public InstructionSymbol (int offset, SequencePoint sequencePoint) { this.Offset = offset; this.SequencePoint = sequencePoint; } } public sealed class MethodSymbols { internal int code_size; internal string method_name; internal MetadataToken method_token; internal MetadataToken local_var_token; internal Collection variables; public Collection instructions; public bool HasVariables { get { return !Mixin.IsNullOrEmpty (variables); } } public Collection Variables { get { if (variables == null) variables = new Collection (); return variables; } } public Collection Instructions { get { if (instructions == null) instructions = new Collection (); return instructions; } } public int CodeSize { get { return code_size; } } public string MethodName { get { return method_name; } } public MetadataToken MethodToken { get { return method_token; } } public MetadataToken LocalVarToken { get { return local_var_token; } } internal MethodSymbols (string methodName) { this.method_name = methodName; } public MethodSymbols (MetadataToken methodToken) { this.method_token = methodToken; } } public delegate Instruction InstructionMapper (int offset); public interface ISymbolReader : IDisposable { bool ProcessDebugHeader (ImageDebugDirectory directory, byte [] header); void Read (MethodBody body, InstructionMapper mapper); void Read (MethodSymbols symbols); } public interface ISymbolReaderProvider { ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName); ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream); } static class SymbolProvider { static readonly string symbol_kind = Type.GetType ("Mono.Runtime") != null ? "Mdb" : "Pdb"; static SR.AssemblyName GetPlatformSymbolAssemblyName () { var cecil_name = typeof (SymbolProvider).Assembly.GetName (); var name = new SR.AssemblyName { Name = "Mono.Cecil." + symbol_kind, Version = cecil_name.Version, }; name.SetPublicKeyToken (cecil_name.GetPublicKeyToken ()); return name; } static Type GetPlatformType (string fullname) { var type = Type.GetType (fullname); if (type != null) return type; var assembly_name = GetPlatformSymbolAssemblyName (); type = Type.GetType (fullname + ", " + assembly_name.FullName); if (type != null) return type; try { var assembly = SR.Assembly.Load (assembly_name); if (assembly != null) return assembly.GetType (fullname); } catch (FileNotFoundException) { } return null; } static ISymbolReaderProvider reader_provider; public static ISymbolReaderProvider GetPlatformReaderProvider () { if (reader_provider != null) return reader_provider; var type = GetPlatformType (GetProviderTypeName ("ReaderProvider")); if (type == null) return null; return reader_provider = (ISymbolReaderProvider) Activator.CreateInstance (type); } static string GetProviderTypeName (string name) { return "Mono.Cecil." + symbol_kind + "." + symbol_kind + name; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/VariableDefinition.cs ================================================ // // VariableDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil.Cil { public sealed class VariableDefinition : VariableReference { public bool IsPinned { get { return variable_type.IsPinned; } } public VariableDefinition (TypeReference variableType) : base (variableType) { } public VariableDefinition (string name, TypeReference variableType) : base (name, variableType) { } public override VariableDefinition Resolve () { return this; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/VariableReference.cs ================================================ // // VariableReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil.Cil { public abstract class VariableReference { string name; internal int index = -1; protected TypeReference variable_type; public string Name { get { return name; } set { name = value; } } public TypeReference VariableType { get { return variable_type; } set { variable_type = value; } } public int Index { get { return index; } } internal VariableReference (TypeReference variable_type) : this (string.Empty, variable_type) { } internal VariableReference (string name, TypeReference variable_type) { this.name = name; this.variable_type = variable_type; } public abstract VariableDefinition Resolve (); public override string ToString () { if (!string.IsNullOrEmpty (name)) return name; if (index >= 0) return "V_" + index; return string.Empty; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/BlobHeap.cs ================================================ // // BlobHeap.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.PE; namespace Mono.Cecil.Metadata { sealed class BlobHeap : Heap { public BlobHeap(Section section, uint start, uint size) : base(section, start, size) { } public byte[] Read(uint index) { if (index == 0 || index > Size - 1) return Empty.Array; var data = Section.Data; int position = (int)(index + Offset); int length = (int)Mixin.ReadCompressedUInt32(data, ref position); var buffer = new byte[length]; Buffer.BlockCopy(data, position, buffer, 0, length); return buffer; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/Buffers.cs ================================================ // // TableHeapBuffer.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using System.Text; using Mono.Cecil.PE; using RVA = System.UInt32; ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/CodedIndex.cs ================================================ // // CodedIndex.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil.Metadata { enum CodedIndex { TypeDefOrRef, HasConstant, HasCustomAttribute, HasFieldMarshal, HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef, MemberForwarded, Implementation, CustomAttributeType, ResolutionScope, TypeOrMethodDef } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/ElementType.cs ================================================ // // ElementType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil.Metadata { enum ElementType : byte { None = 0x00, Void = 0x01, Boolean = 0x02, Char = 0x03, I1 = 0x04, U1 = 0x05, I2 = 0x06, U2 = 0x07, I4 = 0x08, U4 = 0x09, I8 = 0x0a, U8 = 0x0b, R4 = 0x0c, R8 = 0x0d, String = 0x0e, Ptr = 0x0f, // Followed by token ByRef = 0x10, // Followed by token ValueType = 0x11, // Followed by token Class = 0x12, // Followed by token Var = 0x13, // Followed by generic parameter number Array = 0x14, // GenericInst = 0x15, // ... */ TypedByRef = 0x16, I = 0x18, // System.IntPtr U = 0x19, // System.UIntPtr FnPtr = 0x1b, // Followed by full method signature Object = 0x1c, // System.Object SzArray = 0x1d, // Single-dim array with 0 lower bound MVar = 0x1e, // Followed by generic parameter number CModReqD = 0x1f, // Required modifier : followed by a TypeDef or TypeRef token CModOpt = 0x20, // Optional modifier : followed by a TypeDef or TypeRef token Internal = 0x21, // Implemented within the CLI Modifier = 0x40, // Or'd with following element types Sentinel = 0x41, // Sentinel for varargs method signature Pinned = 0x45, // Denotes a local variable that points at a pinned object // special undocumented constants Type = 0x50, Boxed = 0x51, Enum = 0x55 } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/GuidHeap.cs ================================================ // // GuidHeap.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.PE; namespace Mono.Cecil.Metadata { sealed class GuidHeap : Heap { public GuidHeap (Section section, uint start, uint size) : base (section, start, size) { } public Guid Read (uint index) { if (index == 0) return new Guid (); const int guid_size = 16; var buffer = new byte [guid_size]; index--; Buffer.BlockCopy (Section.Data, (int) (Offset + index), buffer, 0, guid_size); return new Guid (buffer); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/Heap.cs ================================================ // // Heap.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using Mono.Cecil.PE; namespace Mono.Cecil.Metadata { abstract class Heap { public int IndexSize; public readonly Section Section; public readonly uint Offset; public readonly uint Size; protected Heap (Section section, uint offset, uint size) { this.Section = section; this.Offset = offset; this.Size = size; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/MetadataToken.cs ================================================ // // MetadataToken.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public struct MetadataToken { readonly uint token; public uint RID { get { return token & 0x00ffffff; } } public TokenType TokenType { get { return (TokenType) (token & 0xff000000); } } public static readonly MetadataToken Zero = new MetadataToken ((uint) 0); public MetadataToken (uint token) { this.token = token; } public MetadataToken (TokenType type) : this (type, 0) { } public MetadataToken (TokenType type, uint rid) { token = (uint) type | rid; } public MetadataToken (TokenType type, int rid) { token = (uint) type | (uint) rid; } public int ToInt32 () { return (int) token; } public uint ToUInt32 () { return token; } public override int GetHashCode () { return (int) token; } public override bool Equals (object obj) { if (obj is MetadataToken) { var other = (MetadataToken) obj; return other.token == token; } return false; } public static bool operator == (MetadataToken one, MetadataToken other) { return one.token == other.token; } public static bool operator != (MetadataToken one, MetadataToken other) { return one.token != other.token; } public override string ToString () { return string.Format ("[{0}:0x{1}]", TokenType, RID.ToString ("x4")); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/Row.cs ================================================ // // Row.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System.Collections.Generic; namespace Mono.Cecil.Metadata { class Row { internal T1 Col1; internal T2 Col2; public Row (T1 col1, T2 col2) { Col1 = col1; Col2 = col2; } } class Row { internal T1 Col1; internal T2 Col2; internal T3 Col3; public Row (T1 col1, T2 col2, T3 col3) { Col1 = col1; Col2 = col2; Col3 = col3; } } class Row { internal T1 Col1; internal T2 Col2; internal T3 Col3; internal T4 Col4; public Row (T1 col1, T2 col2, T3 col3, T4 col4) { Col1 = col1; Col2 = col2; Col3 = col3; Col4 = col4; } } class Row { internal T1 Col1; internal T2 Col2; internal T3 Col3; internal T4 Col4; internal T5 Col5; public Row (T1 col1, T2 col2, T3 col3, T4 col4, T5 col5) { Col1 = col1; Col2 = col2; Col3 = col3; Col4 = col4; Col5 = col5; } } class Row { internal T1 Col1; internal T2 Col2; internal T3 Col3; internal T4 Col4; internal T5 Col5; internal T6 Col6; public Row (T1 col1, T2 col2, T3 col3, T4 col4, T5 col5, T6 col6) { Col1 = col1; Col2 = col2; Col3 = col3; Col4 = col4; Col5 = col5; Col6 = col6; } } class Row { internal T1 Col1; internal T2 Col2; internal T3 Col3; internal T4 Col4; internal T5 Col5; internal T6 Col6; internal T7 Col7; internal T8 Col8; internal T9 Col9; public Row (T1 col1, T2 col2, T3 col3, T4 col4, T5 col5, T6 col6, T7 col7, T8 col8, T9 col9) { Col1 = col1; Col2 = col2; Col3 = col3; Col4 = col4; Col5 = col5; Col6 = col6; Col7 = col7; Col8 = col8; Col9 = col9; } } sealed class RowEqualityComparer : IEqualityComparer>, IEqualityComparer>, IEqualityComparer> { public bool Equals (Row x, Row y) { return x.Col1 == y.Col1 && x.Col2 == y.Col2; } public int GetHashCode (Row obj) { string x = obj.Col1, y = obj.Col2; return (x != null ? x.GetHashCode () : 0) ^ (y != null ? y.GetHashCode () : 0); } public bool Equals (Row x, Row y) { return x.Col1 == y.Col1 && x.Col2 == y.Col2; } public int GetHashCode (Row obj) { return (int) (obj.Col1 ^ obj.Col2); } public bool Equals (Row x, Row y) { return x.Col1 == y.Col1 && x.Col2 == y.Col2 && x.Col3 == y.Col3; } public int GetHashCode (Row obj) { return (int) (obj.Col1 ^ obj.Col2 ^ obj.Col3); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/StringHeap.cs ================================================ // // StringHeap.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using System.Text; using Mono.Cecil.PE; namespace Mono.Cecil.Metadata { class StringHeap : Heap { readonly Dictionary strings = new Dictionary (); public StringHeap (Section section, uint start, uint size) : base (section, start, size) { } public string Read (uint index) { if (index == 0) return string.Empty; string @string; if (strings.TryGetValue (index, out @string)) return @string; if (index > Size - 1) return string.Empty; @string = ReadStringAt (index); if (@string.Length != 0) strings.Add (index, @string); return @string; } protected virtual string ReadStringAt (uint index) { int length = 0; byte [] data = Section.Data; int start = (int) (index + Offset); for (int i = start; ; i++) { if (data [i] == 0) break; length++; } return Encoding.UTF8.GetString (data, start, length); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/TableHeap.cs ================================================ // // TableHeap.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.PE; namespace Mono.Cecil.Metadata { enum Table : byte { Module = 0x00, TypeRef = 0x01, TypeDef = 0x02, FieldPtr = 0x03, Field = 0x04, MethodPtr = 0x05, Method = 0x06, ParamPtr = 0x07, Param = 0x08, InterfaceImpl = 0x09, MemberRef = 0x0a, Constant = 0x0b, CustomAttribute = 0x0c, FieldMarshal = 0x0d, DeclSecurity = 0x0e, ClassLayout = 0x0f, FieldLayout = 0x10, StandAloneSig = 0x11, EventMap = 0x12, EventPtr = 0x13, Event = 0x14, PropertyMap = 0x15, PropertyPtr = 0x16, Property = 0x17, MethodSemantics = 0x18, MethodImpl = 0x19, ModuleRef = 0x1a, TypeSpec = 0x1b, ImplMap = 0x1c, FieldRVA = 0x1d, EncLog = 0x1e, EncMap = 0x1f, Assembly = 0x20, AssemblyProcessor = 0x21, AssemblyOS = 0x22, AssemblyRef = 0x23, AssemblyRefProcessor = 0x24, AssemblyRefOS = 0x25, File = 0x26, ExportedType = 0x27, ManifestResource = 0x28, NestedClass = 0x29, GenericParam = 0x2a, MethodSpec = 0x2b, GenericParamConstraint = 0x2c, } struct TableInformation { public uint Offset; public uint Length; public uint RowSize; } sealed class TableHeap : Heap { public long Valid; public long Sorted; public const int TableCount = 45; public readonly TableInformation [] Tables = new TableInformation [TableCount]; public TableInformation this [Table table] { get { return Tables [(int) table]; } } public TableHeap (Section section, uint start, uint size) : base (section, start, size) { } public bool HasTable (Table table) { return (Valid & (1L << (int) table)) != 0; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/TokenType.cs ================================================ // // TokenType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public enum TokenType : uint { Module = 0x00000000, TypeRef = 0x01000000, TypeDef = 0x02000000, Field = 0x04000000, Method = 0x06000000, Param = 0x08000000, InterfaceImpl = 0x09000000, MemberRef = 0x0a000000, CustomAttribute = 0x0c000000, Permission = 0x0e000000, Signature = 0x11000000, Event = 0x14000000, Property = 0x17000000, ModuleRef = 0x1a000000, TypeSpec = 0x1b000000, Assembly = 0x20000000, AssemblyRef = 0x23000000, File = 0x26000000, ExportedType = 0x27000000, ManifestResource = 0x28000000, GenericParam = 0x2a000000, MethodSpec = 0x2b000000, String = 0x70000000, } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/UserStringHeap.cs ================================================ // // UserStringHeap.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.PE; namespace Mono.Cecil.Metadata { sealed class UserStringHeap : StringHeap { public UserStringHeap(Section section, uint start, uint size) : base(section, start, size) { } protected override string ReadStringAt(uint index) { byte[] data = Section.Data; int start = (int)(index + Offset); uint length = (uint)(Mixin.ReadCompressedUInt32(data, ref start) & ~1); if (length < 1) return string.Empty; var chars = new char[length / 2]; for (int i = start, j = 0; i < start + length; i += 2) chars[j++] = (char)(data[i] | (data[i + 1] << 8)); return new string(chars); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/Utilities.cs ================================================ // // Utilities.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.Metadata; namespace Mono.Cecil { static partial class Mixin { public static uint ReadCompressedUInt32(byte[] data, ref int position) { uint integer; if ((data[position] & 0x80) == 0) { integer = data[position]; position++; } else if ((data[position] & 0x40) == 0) { integer = (uint)(data[position] & ~0x80) << 8; integer |= data[position + 1]; position += 2; } else { integer = (uint)(data[position] & ~0xc0) << 24; integer |= (uint)data[position + 1] << 16; integer |= (uint)data[position + 2] << 8; integer |= (uint)data[position + 3]; position += 4; } return integer; } public static MetadataToken GetMetadataToken(CodedIndex self, uint data) { uint rid; TokenType token_type; switch (self) { case CodedIndex.TypeDefOrRef: rid = data >> 2; switch (data & 3) { case 0: token_type = TokenType.TypeDef; goto ret; case 1: token_type = TokenType.TypeRef; goto ret; case 2: token_type = TokenType.TypeSpec; goto ret; default: goto exit; } case CodedIndex.HasConstant: rid = data >> 2; switch (data & 3) { case 0: token_type = TokenType.Field; goto ret; case 1: token_type = TokenType.Param; goto ret; case 2: token_type = TokenType.Property; goto ret; default: goto exit; } case CodedIndex.HasCustomAttribute: rid = data >> 5; switch (data & 31) { case 0: token_type = TokenType.Method; goto ret; case 1: token_type = TokenType.Field; goto ret; case 2: token_type = TokenType.TypeRef; goto ret; case 3: token_type = TokenType.TypeDef; goto ret; case 4: token_type = TokenType.Param; goto ret; case 5: token_type = TokenType.InterfaceImpl; goto ret; case 6: token_type = TokenType.MemberRef; goto ret; case 7: token_type = TokenType.Module; goto ret; case 8: token_type = TokenType.Permission; goto ret; case 9: token_type = TokenType.Property; goto ret; case 10: token_type = TokenType.Event; goto ret; case 11: token_type = TokenType.Signature; goto ret; case 12: token_type = TokenType.ModuleRef; goto ret; case 13: token_type = TokenType.TypeSpec; goto ret; case 14: token_type = TokenType.Assembly; goto ret; case 15: token_type = TokenType.AssemblyRef; goto ret; case 16: token_type = TokenType.File; goto ret; case 17: token_type = TokenType.ExportedType; goto ret; case 18: token_type = TokenType.ManifestResource; goto ret; case 19: token_type = TokenType.GenericParam; goto ret; default: goto exit; } case CodedIndex.HasFieldMarshal: rid = data >> 1; switch (data & 1) { case 0: token_type = TokenType.Field; goto ret; case 1: token_type = TokenType.Param; goto ret; default: goto exit; } case CodedIndex.HasDeclSecurity: rid = data >> 2; switch (data & 3) { case 0: token_type = TokenType.TypeDef; goto ret; case 1: token_type = TokenType.Method; goto ret; case 2: token_type = TokenType.Assembly; goto ret; default: goto exit; } case CodedIndex.MemberRefParent: rid = data >> 3; switch (data & 7) { case 0: token_type = TokenType.TypeDef; goto ret; case 1: token_type = TokenType.TypeRef; goto ret; case 2: token_type = TokenType.ModuleRef; goto ret; case 3: token_type = TokenType.Method; goto ret; case 4: token_type = TokenType.TypeSpec; goto ret; default: goto exit; } case CodedIndex.HasSemantics: rid = data >> 1; switch (data & 1) { case 0: token_type = TokenType.Event; goto ret; case 1: token_type = TokenType.Property; goto ret; default: goto exit; } case CodedIndex.MethodDefOrRef: rid = data >> 1; switch (data & 1) { case 0: token_type = TokenType.Method; goto ret; case 1: token_type = TokenType.MemberRef; goto ret; default: goto exit; } case CodedIndex.MemberForwarded: rid = data >> 1; switch (data & 1) { case 0: token_type = TokenType.Field; goto ret; case 1: token_type = TokenType.Method; goto ret; default: goto exit; } case CodedIndex.Implementation: rid = data >> 2; switch (data & 3) { case 0: token_type = TokenType.File; goto ret; case 1: token_type = TokenType.AssemblyRef; goto ret; case 2: token_type = TokenType.ExportedType; goto ret; default: goto exit; } case CodedIndex.CustomAttributeType: rid = data >> 3; switch (data & 7) { case 2: token_type = TokenType.Method; goto ret; case 3: token_type = TokenType.MemberRef; goto ret; default: goto exit; } case CodedIndex.ResolutionScope: rid = data >> 2; switch (data & 3) { case 0: token_type = TokenType.Module; goto ret; case 1: token_type = TokenType.ModuleRef; goto ret; case 2: token_type = TokenType.AssemblyRef; goto ret; case 3: token_type = TokenType.TypeRef; goto ret; default: goto exit; } case CodedIndex.TypeOrMethodDef: rid = data >> 1; switch (data & 1) { case 0: token_type = TokenType.TypeDef; goto ret; case 1: token_type = TokenType.Method; goto ret; default: goto exit; } default: goto exit; } ret: return new MetadataToken(token_type, rid); exit: return MetadataToken.Zero; } public static int GetSize(CodedIndex self, Func counter) { int bits; Table[] tables; switch (self) { case CodedIndex.TypeDefOrRef: bits = 2; tables = new[] { Table.TypeDef, Table.TypeRef, Table.TypeSpec }; break; case CodedIndex.HasConstant: bits = 2; tables = new[] { Table.Field, Table.Param, Table.Property }; break; case CodedIndex.HasCustomAttribute: bits = 5; tables = new[] { Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef, Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef, Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType, Table.ManifestResource, Table.GenericParam }; break; case CodedIndex.HasFieldMarshal: bits = 1; tables = new[] { Table.Field, Table.Param }; break; case CodedIndex.HasDeclSecurity: bits = 2; tables = new[] { Table.TypeDef, Table.Method, Table.Assembly }; break; case CodedIndex.MemberRefParent: bits = 3; tables = new[] { Table.TypeDef, Table.TypeRef, Table.ModuleRef, Table.Method, Table.TypeSpec }; break; case CodedIndex.HasSemantics: bits = 1; tables = new[] { Table.Event, Table.Property }; break; case CodedIndex.MethodDefOrRef: bits = 1; tables = new[] { Table.Method, Table.MemberRef }; break; case CodedIndex.MemberForwarded: bits = 1; tables = new[] { Table.Field, Table.Method }; break; case CodedIndex.Implementation: bits = 2; tables = new[] { Table.File, Table.AssemblyRef, Table.ExportedType }; break; case CodedIndex.CustomAttributeType: bits = 3; tables = new[] { Table.Method, Table.MemberRef }; break; case CodedIndex.ResolutionScope: bits = 2; tables = new[] { Table.Module, Table.ModuleRef, Table.AssemblyRef, Table.TypeRef }; break; case CodedIndex.TypeOrMethodDef: bits = 1; tables = new[] { Table.TypeDef, Table.Method }; break; default: throw new ArgumentException(); } int max = 0; for (int i = 0; i < tables.Length; i++) { max = System.Math.Max(counter(tables[i]), max); } return max < (1 << (16 - bits)) ? 2 : 4; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/BinaryStreamReader.cs ================================================ // // BinaryStreamReader.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.IO; namespace Mono.Cecil.PE { class BinaryStreamReader : BinaryReader { public BinaryStreamReader (Stream stream) : base (stream) { } protected void Advance (int bytes) { BaseStream.Seek (bytes, SeekOrigin.Current); } protected DataDirectory ReadDataDirectory () { return new DataDirectory (ReadUInt32 (), ReadUInt32 ()); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/BinaryStreamWriter.cs ================================================ // // BinaryStreamWriter.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.IO; ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/ByteBuffer.cs ================================================ // // ByteBuffer.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil.PE { class ByteBuffer { internal byte [] buffer; internal int length; internal int position; public ByteBuffer () { this.buffer = Empty.Array; } public ByteBuffer (int length) { this.buffer = new byte [length]; } public ByteBuffer (byte [] buffer) { this.buffer = buffer ?? Empty.Array; this.length = this.buffer.Length; } public void Reset (byte [] buffer) { this.buffer = buffer ?? Empty.Array; this.length = this.buffer.Length; } public void Advance (int length) { position += length; } public byte ReadByte () { return buffer [position++]; } public sbyte ReadSByte () { return (sbyte) ReadByte (); } public byte [] ReadBytes (int length) { var bytes = new byte [length]; Buffer.BlockCopy (buffer, position, bytes, 0, length); position += length; return bytes; } public ushort ReadUInt16 () { ushort value = (ushort) (buffer [position] | (buffer [position + 1] << 8)); position += 2; return value; } public short ReadInt16 () { return (short) ReadUInt16 (); } public uint ReadUInt32 () { uint value = (uint) (buffer [position] | (buffer [position + 1] << 8) | (buffer [position + 2] << 16) | (buffer [position + 3] << 24)); position += 4; return value; } public int ReadInt32 () { return (int) ReadUInt32 (); } public ulong ReadUInt64 () { uint low = ReadUInt32 (); uint high = ReadUInt32 (); return (((ulong) high) << 32) | low; } public long ReadInt64 () { return (long) ReadUInt64 (); } public uint ReadCompressedUInt32 () { byte first = ReadByte (); if ((first & 0x80) == 0) return first; if ((first & 0x40) == 0) return ((uint) (first & ~0x80) << 8) | ReadByte (); return ((uint) (first & ~0xc0) << 24) | (uint) ReadByte () << 16 | (uint) ReadByte () << 8 | ReadByte (); } public int ReadCompressedInt32 () { var value = (int) (ReadCompressedUInt32 () >> 1); if ((value & 1) == 0) return value; if (value < 0x40) return value - 0x40; if (value < 0x2000) return value - 0x2000; if (value < 0x10000000) return value - 0x10000000; return value - 0x20000000; } public float ReadSingle () { if (!BitConverter.IsLittleEndian) { var bytes = ReadBytes (4); Array.Reverse (bytes); return BitConverter.ToSingle (bytes, 0); } float value = BitConverter.ToSingle (buffer, position); position += 4; return value; } public double ReadDouble () { if (!BitConverter.IsLittleEndian) { var bytes = ReadBytes (8); Array.Reverse (bytes); return BitConverter.ToDouble (bytes, 0); } double value = BitConverter.ToDouble (buffer, position); position += 8; return value; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/ByteBufferEqualityComparer.cs ================================================ // // ByteBufferEqualityComparer.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; namespace Mono.Cecil.PE { sealed class ByteBufferEqualityComparer : IEqualityComparer { public bool Equals (ByteBuffer x, ByteBuffer y) { if (x.length != y.length) return false; var x_buffer = x.buffer; var y_buffer = y.buffer; for (int i = 0; i < x.length; i++) if (x_buffer [i] != y_buffer [i]) return false; return true; } public int GetHashCode (ByteBuffer buffer) { #if !BYTE_BUFFER_WELL_DISTRIBUTED_HASH var hash = 0; var bytes = buffer.buffer; for (int i = 0; i < buffer.length; i++) hash = (hash * 37) ^ bytes [i]; return hash; #else const uint p = 16777619; uint hash = 2166136261; var bytes = buffer.buffer; for (int i = 0; i < buffer.length; i++) hash = (hash ^ bytes [i]) * p; hash += hash << 13; hash ^= hash >> 7; hash += hash << 3; hash ^= hash >> 17; hash += hash << 5; return (int) hash; #endif } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/DataDirectory.cs ================================================ // // DataDirectory.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using RVA = System.UInt32; namespace Mono.Cecil.PE { struct DataDirectory { public readonly RVA VirtualAddress; public readonly uint Size; public bool IsZero { get { return VirtualAddress == 0 && Size == 0; } } public DataDirectory (RVA rva, uint size) { this.VirtualAddress = rva; this.Size = size; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/Image.cs ================================================ // // Image.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono; using Mono.Cecil.Cil; using Mono.Cecil.Metadata; using RVA = System.UInt32; namespace Mono.Cecil.PE { sealed class Image { public ModuleKind Kind; public TargetRuntime Runtime; public TargetArchitecture Architecture; public ModuleCharacteristics Characteristics; public string FileName; public Section[] Sections; public Section MetadataSection; public uint EntryPointToken; public ModuleAttributes Attributes; public DataDirectory Debug; public DataDirectory Resources; public DataDirectory StrongName; public StringHeap StringHeap; public BlobHeap BlobHeap; public UserStringHeap UserStringHeap; public GuidHeap GuidHeap; public TableHeap TableHeap; readonly int[] coded_index_sizes = new int[13]; readonly Func counter; public Image() { counter = GetTableLength; } public bool HasTable(Table table) { return GetTableLength(table) > 0; } public int GetTableLength(Table table) { return (int)TableHeap[table].Length; } public int GetTableIndexSize(Table table) { return GetTableLength(table) < 65536 ? 2 : 4; } public int GetCodedIndexSize(CodedIndex coded_index) { var index = (int)coded_index; var size = coded_index_sizes[index]; if (size != 0) return size; return coded_index_sizes[index] = Mixin.GetSize(coded_index, counter); } public uint ResolveVirtualAddress(RVA rva) { var section = GetSectionAtVirtualAddress(rva); if (section == null) throw new ArgumentOutOfRangeException(); return ResolveVirtualAddressInSection(rva, section); } public uint ResolveVirtualAddressInSection(RVA rva, Section section) { return rva + section.PointerToRawData - section.VirtualAddress; } public Section GetSection(string name) { var sections = this.Sections; for (int i = 0; i < sections.Length; i++) { var section = sections[i]; if (section.Name == name) return section; } return null; } public Section GetSectionAtVirtualAddress(RVA rva) { var sections = this.Sections; for (int i = 0; i < sections.Length; i++) { var section = sections[i]; if (rva >= section.VirtualAddress && rva < section.VirtualAddress + section.SizeOfRawData) return section; } return null; } public ImageDebugDirectory GetDebugHeader(out byte[] header) { var section = GetSectionAtVirtualAddress(Debug.VirtualAddress); var buffer = new ByteBuffer(section.Data); buffer.position = (int)(Debug.VirtualAddress - section.VirtualAddress); var directory = new ImageDebugDirectory { Characteristics = buffer.ReadInt32(), TimeDateStamp = buffer.ReadInt32(), MajorVersion = buffer.ReadInt16(), MinorVersion = buffer.ReadInt16(), Type = buffer.ReadInt32(), SizeOfData = buffer.ReadInt32(), AddressOfRawData = buffer.ReadInt32(), PointerToRawData = buffer.ReadInt32(), }; buffer.position = (int)(directory.PointerToRawData - section.PointerToRawData); header = new byte[directory.SizeOfData]; Buffer.BlockCopy(buffer.buffer, buffer.position, header, 0, header.Length); return directory; } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/ImageReader.cs ================================================ // // ImageReader.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.IO; using Mono.Cecil.Metadata; using RVA = System.UInt32; namespace Mono.Cecil.PE { sealed class ImageReader : BinaryStreamReader { readonly Image image; DataDirectory cli; DataDirectory metadata; public ImageReader(Stream stream) : base(stream) { image = new Image(); image.FileName = Mixin.GetFullyQualifiedName(stream); } void MoveTo(DataDirectory directory) { BaseStream.Position = image.ResolveVirtualAddress(directory.VirtualAddress); } void MoveTo(uint position) { BaseStream.Position = position; } void ReadImage() { if (BaseStream.Length < 128) throw new BadImageFormatException(); // - DOSHeader // PE 2 // Start 58 // Lfanew 4 // End 64 if (ReadUInt16() != 0x5a4d) throw new BadImageFormatException(); Advance(58); MoveTo(ReadUInt32()); if (ReadUInt32() != 0x00004550) throw new BadImageFormatException(); // - PEFileHeader // Machine 2 image.Architecture = ReadArchitecture(); // NumberOfSections 2 ushort sections = ReadUInt16(); // TimeDateStamp 4 // PointerToSymbolTable 4 // NumberOfSymbols 4 // OptionalHeaderSize 2 Advance(14); // Characteristics 2 ushort characteristics = ReadUInt16(); ushort subsystem, dll_characteristics; ReadOptionalHeaders(out subsystem, out dll_characteristics); ReadSections(sections); ReadCLIHeader(); ReadMetadata(); image.Kind = GetModuleKind(characteristics, subsystem); image.Characteristics = (ModuleCharacteristics)dll_characteristics; } TargetArchitecture ReadArchitecture() { var machine = ReadUInt16(); switch (machine) { case 0x014c: return TargetArchitecture.I386; case 0x8664: return TargetArchitecture.AMD64; case 0x0200: return TargetArchitecture.IA64; case 0x01c4: return TargetArchitecture.ARMv7; } throw new NotSupportedException(); } static ModuleKind GetModuleKind(ushort characteristics, ushort subsystem) { if ((characteristics & 0x2000) != 0) // ImageCharacteristics.Dll return ModuleKind.Dll; if (subsystem == 0x2 || subsystem == 0x9) // SubSystem.WindowsGui || SubSystem.WindowsCeGui return ModuleKind.Windows; return ModuleKind.Console; } void ReadOptionalHeaders(out ushort subsystem, out ushort dll_characteristics) { // - PEOptionalHeader // - StandardFieldsHeader // Magic 2 bool pe64 = ReadUInt16() == 0x20b; // pe32 || pe64 // LMajor 1 // LMinor 1 // CodeSize 4 // InitializedDataSize 4 // UninitializedDataSize4 // EntryPointRVA 4 // BaseOfCode 4 // BaseOfData 4 || 0 // - NTSpecificFieldsHeader // ImageBase 4 || 8 // SectionAlignment 4 // FileAlignement 4 // OSMajor 2 // OSMinor 2 // UserMajor 2 // UserMinor 2 // SubSysMajor 2 // SubSysMinor 2 // Reserved 4 // ImageSize 4 // HeaderSize 4 // FileChecksum 4 Advance(66); // SubSystem 2 subsystem = ReadUInt16(); // DLLFlags 2 dll_characteristics = ReadUInt16(); // StackReserveSize 4 || 8 // StackCommitSize 4 || 8 // HeapReserveSize 4 || 8 // HeapCommitSize 4 || 8 // LoaderFlags 4 // NumberOfDataDir 4 // - DataDirectoriesHeader // ExportTable 8 // ImportTable 8 // ResourceTable 8 // ExceptionTable 8 // CertificateTable 8 // BaseRelocationTable 8 Advance(pe64 ? 88 : 72); // Debug 8 image.Debug = ReadDataDirectory(); // Copyright 8 // GlobalPtr 8 // TLSTable 8 // LoadConfigTable 8 // BoundImport 8 // IAT 8 // DelayImportDescriptor8 Advance(56); // CLIHeader 8 cli = ReadDataDirectory(); if (cli.IsZero) throw new BadImageFormatException(); // Reserved 8 Advance(8); } string ReadAlignedString(int length) { int read = 0; var buffer = new char[length]; while (read < length) { var current = ReadByte(); if (current == 0) break; buffer[read++] = (char)current; } Advance(-1 + ((read + 4) & ~3) - read); return new string(buffer, 0, read); } string ReadZeroTerminatedString(int length) { int read = 0; var buffer = new char[length]; var bytes = ReadBytes(length); while (read < length) { var current = bytes[read]; if (current == 0) break; buffer[read++] = (char)current; } return new string(buffer, 0, read); } void ReadSections(ushort count) { var sections = new Section[count]; for (int i = 0; i < count; i++) { var section = new Section(); // Name section.Name = ReadZeroTerminatedString(8); // VirtualSize 4 Advance(4); // VirtualAddress 4 section.VirtualAddress = ReadUInt32(); // SizeOfRawData 4 section.SizeOfRawData = ReadUInt32(); // PointerToRawData 4 section.PointerToRawData = ReadUInt32(); // PointerToRelocations 4 // PointerToLineNumbers 4 // NumberOfRelocations 2 // NumberOfLineNumbers 2 // Characteristics 4 Advance(16); sections[i] = section; ReadSectionData(section); } image.Sections = sections; } void ReadSectionData(Section section) { var position = BaseStream.Position; MoveTo(section.PointerToRawData); var length = (int)section.SizeOfRawData; var data = new byte[length]; int offset = 0, read; while ((read = Read(data, offset, length - offset)) > 0) offset += read; section.Data = data; BaseStream.Position = position; } void ReadCLIHeader() { MoveTo(cli); // - CLIHeader // Cb 4 // MajorRuntimeVersion 2 // MinorRuntimeVersion 2 Advance(8); // Metadata 8 metadata = ReadDataDirectory(); // Flags 4 image.Attributes = (ModuleAttributes)ReadUInt32(); // EntryPointToken 4 image.EntryPointToken = ReadUInt32(); // Resources 8 image.Resources = ReadDataDirectory(); // StrongNameSignature 8 image.StrongName = ReadDataDirectory(); // CodeManagerTable 8 // VTableFixups 8 // ExportAddressTableJumps 8 // ManagedNativeHeader 8 } void ReadMetadata() { MoveTo(metadata); if (ReadUInt32() != 0x424a5342) throw new BadImageFormatException(); // MajorVersion 2 // MinorVersion 2 // Reserved 4 Advance(8); var version = ReadZeroTerminatedString(ReadInt32()); image.Runtime = Mixin.ParseRuntime(version); // Flags 2 Advance(2); var streams = ReadUInt16(); var section = image.GetSectionAtVirtualAddress(metadata.VirtualAddress); if (section == null) throw new BadImageFormatException(); image.MetadataSection = section; for (int i = 0; i < streams; i++) ReadMetadataStream(section); if (image.TableHeap != null) ReadTableHeap(); } void ReadMetadataStream(Section section) { // Offset 4 uint start = metadata.VirtualAddress - section.VirtualAddress + ReadUInt32(); // relative to the section start // Size 4 uint size = ReadUInt32(); var name = ReadAlignedString(16); switch (name) { case "#~": case "#-": image.TableHeap = new TableHeap(section, start, size); break; case "#Strings": image.StringHeap = new StringHeap(section, start, size); break; case "#Blob": image.BlobHeap = new BlobHeap(section, start, size); break; case "#GUID": image.GuidHeap = new GuidHeap(section, start, size); break; case "#US": image.UserStringHeap = new UserStringHeap(section, start, size); break; } } void ReadTableHeap() { var heap = image.TableHeap; uint start = heap.Section.PointerToRawData; MoveTo(heap.Offset + start); // Reserved 4 // MajorVersion 1 // MinorVersion 1 Advance(6); // HeapSizes 1 var sizes = ReadByte(); // Reserved2 1 Advance(1); // Valid 8 heap.Valid = ReadInt64(); // Sorted 8 heap.Sorted = ReadInt64(); for (int i = 0; i < TableHeap.TableCount; i++) { if (!heap.HasTable((Table)i)) continue; heap.Tables[i].Length = ReadUInt32(); } SetIndexSize(image.StringHeap, sizes, 0x1); SetIndexSize(image.GuidHeap, sizes, 0x2); SetIndexSize(image.BlobHeap, sizes, 0x4); ComputeTableInformations(); } static void SetIndexSize(Heap heap, uint sizes, byte flag) { if (heap == null) return; heap.IndexSize = (sizes & flag) > 0 ? 4 : 2; } int GetTableIndexSize(Table table) { return image.GetTableIndexSize(table); } int GetCodedIndexSize(CodedIndex index) { return image.GetCodedIndexSize(index); } void ComputeTableInformations() { uint offset = (uint)BaseStream.Position - image.MetadataSection.PointerToRawData; // header int stridx_size = image.StringHeap.IndexSize; int blobidx_size = image.BlobHeap != null ? image.BlobHeap.IndexSize : 2; var heap = image.TableHeap; var tables = heap.Tables; for (int i = 0; i < TableHeap.TableCount; i++) { var table = (Table)i; if (!heap.HasTable(table)) continue; int size; switch (table) { case Table.Module: size = 2 // Generation + stridx_size // Name + (image.GuidHeap.IndexSize * 3); // Mvid, EncId, EncBaseId break; case Table.TypeRef: size = GetCodedIndexSize(CodedIndex.ResolutionScope) // ResolutionScope + (stridx_size * 2); // Name, Namespace break; case Table.TypeDef: size = 4 // Flags + (stridx_size * 2) // Name, Namespace + GetCodedIndexSize(CodedIndex.TypeDefOrRef) // BaseType + GetTableIndexSize(Table.Field) // FieldList + GetTableIndexSize(Table.Method); // MethodList break; case Table.FieldPtr: size = GetTableIndexSize(Table.Field); // Field break; case Table.Field: size = 2 // Flags + stridx_size // Name + blobidx_size; // Signature break; case Table.MethodPtr: size = GetTableIndexSize(Table.Method); // Method break; case Table.Method: size = 8 // Rva 4, ImplFlags 2, Flags 2 + stridx_size // Name + blobidx_size // Signature + GetTableIndexSize(Table.Param); // ParamList break; case Table.ParamPtr: size = GetTableIndexSize(Table.Param); // Param break; case Table.Param: size = 4 // Flags 2, Sequence 2 + stridx_size; // Name break; case Table.InterfaceImpl: size = GetTableIndexSize(Table.TypeDef) // Class + GetCodedIndexSize(CodedIndex.TypeDefOrRef); // Interface break; case Table.MemberRef: size = GetCodedIndexSize(CodedIndex.MemberRefParent) // Class + stridx_size // Name + blobidx_size; // Signature break; case Table.Constant: size = 2 // Type + GetCodedIndexSize(CodedIndex.HasConstant) // Parent + blobidx_size; // Value break; case Table.CustomAttribute: size = GetCodedIndexSize(CodedIndex.HasCustomAttribute) // Parent + GetCodedIndexSize(CodedIndex.CustomAttributeType) // Type + blobidx_size; // Value break; case Table.FieldMarshal: size = GetCodedIndexSize(CodedIndex.HasFieldMarshal) // Parent + blobidx_size; // NativeType break; case Table.DeclSecurity: size = 2 // Action + GetCodedIndexSize(CodedIndex.HasDeclSecurity) // Parent + blobidx_size; // PermissionSet break; case Table.ClassLayout: size = 6 // PackingSize 2, ClassSize 4 + GetTableIndexSize(Table.TypeDef); // Parent break; case Table.FieldLayout: size = 4 // Offset + GetTableIndexSize(Table.Field); // Field break; case Table.StandAloneSig: size = blobidx_size; // Signature break; case Table.EventMap: size = GetTableIndexSize(Table.TypeDef) // Parent + GetTableIndexSize(Table.Event); // EventList break; case Table.EventPtr: size = GetTableIndexSize(Table.Event); // Event break; case Table.Event: size = 2 // Flags + stridx_size // Name + GetCodedIndexSize(CodedIndex.TypeDefOrRef); // EventType break; case Table.PropertyMap: size = GetTableIndexSize(Table.TypeDef) // Parent + GetTableIndexSize(Table.Property); // PropertyList break; case Table.PropertyPtr: size = GetTableIndexSize(Table.Property); // Property break; case Table.Property: size = 2 // Flags + stridx_size // Name + blobidx_size; // Type break; case Table.MethodSemantics: size = 2 // Semantics + GetTableIndexSize(Table.Method) // Method + GetCodedIndexSize(CodedIndex.HasSemantics); // Association break; case Table.MethodImpl: size = GetTableIndexSize(Table.TypeDef) // Class + GetCodedIndexSize(CodedIndex.MethodDefOrRef) // MethodBody + GetCodedIndexSize(CodedIndex.MethodDefOrRef); // MethodDeclaration break; case Table.ModuleRef: size = stridx_size; // Name break; case Table.TypeSpec: size = blobidx_size; // Signature break; case Table.ImplMap: size = 2 // MappingFlags + GetCodedIndexSize(CodedIndex.MemberForwarded) // MemberForwarded + stridx_size // ImportName + GetTableIndexSize(Table.ModuleRef); // ImportScope break; case Table.FieldRVA: size = 4 // RVA + GetTableIndexSize(Table.Field); // Field break; case Table.EncLog: case Table.EncMap: size = 4; break; case Table.Assembly: size = 16 // HashAlgId 4, Version 4 * 2, Flags 4 + blobidx_size // PublicKey + (stridx_size * 2); // Name, Culture break; case Table.AssemblyProcessor: size = 4; // Processor break; case Table.AssemblyOS: size = 12; // Platform 4, Version 2 * 4 break; case Table.AssemblyRef: size = 12 // Version 2 * 4 + Flags 4 + (blobidx_size * 2) // PublicKeyOrToken, HashValue + (stridx_size * 2); // Name, Culture break; case Table.AssemblyRefProcessor: size = 4 // Processor + GetTableIndexSize(Table.AssemblyRef); // AssemblyRef break; case Table.AssemblyRefOS: size = 12 // Platform 4, Version 2 * 4 + GetTableIndexSize(Table.AssemblyRef); // AssemblyRef break; case Table.File: size = 4 // Flags + stridx_size // Name + blobidx_size; // HashValue break; case Table.ExportedType: size = 8 // Flags 4, TypeDefId 4 + (stridx_size * 2) // Name, Namespace + GetCodedIndexSize(CodedIndex.Implementation); // Implementation break; case Table.ManifestResource: size = 8 // Offset, Flags + stridx_size // Name + GetCodedIndexSize(CodedIndex.Implementation); // Implementation break; case Table.NestedClass: size = GetTableIndexSize(Table.TypeDef) // NestedClass + GetTableIndexSize(Table.TypeDef); // EnclosingClass break; case Table.GenericParam: size = 4 // Number, Flags + GetCodedIndexSize(CodedIndex.TypeOrMethodDef) // Owner + stridx_size; // Name break; case Table.MethodSpec: size = GetCodedIndexSize(CodedIndex.MethodDefOrRef) // Method + blobidx_size; // Instantiation break; case Table.GenericParamConstraint: size = GetTableIndexSize(Table.GenericParam) // Owner + GetCodedIndexSize(CodedIndex.TypeDefOrRef); // Constraint break; default: throw new NotSupportedException(); } tables[i].RowSize = (uint)size; tables[i].Offset = offset; offset += (uint)size * tables[i].Length; } } public static Image ReadImageFrom(Stream stream) { try { var reader = new ImageReader(stream); reader.ReadImage(); return reader.image; } catch (EndOfStreamException e) { throw new BadImageFormatException(Mixin.GetFullyQualifiedName(stream), e); } } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/ImageWriter.cs ================================================ ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/Section.cs ================================================ // // Section.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using RVA = System.UInt32; namespace Mono.Cecil.PE { sealed class Section { public string Name; public RVA VirtualAddress; public uint VirtualSize; public uint SizeOfRawData; public uint PointerToRawData; public byte [] Data; } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/TextMap.cs ================================================ ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Collections.Generic/Collection.cs ================================================ // // Collection.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections; using System.Collections.Generic; namespace Mono.Collections.Generic { public class Collection : IList, IList { internal T [] items; internal int size; int version; public int Count { get { return size; } } public T this [int index] { get { if (index >= size) throw new ArgumentOutOfRangeException (); return items [index]; } set { CheckIndex (index); if (index == size) throw new ArgumentOutOfRangeException (); OnSet (value, index); items [index] = value; } } bool ICollection.IsReadOnly { get { return false; } } bool IList.IsFixedSize { get { return false; } } bool IList.IsReadOnly { get { return false; } } object IList.this [int index] { get { return this [index]; } set { CheckIndex (index); try { this [index] = (T) value; return; } catch (InvalidCastException) { } catch (NullReferenceException) { } throw new ArgumentException (); } } int ICollection.Count { get { return Count; } } bool ICollection.IsSynchronized { get { return false; } } object ICollection.SyncRoot { get { return this; } } public Collection () { items = Empty.Array; } public Collection (int capacity) { if (capacity < 0) throw new ArgumentOutOfRangeException (); items = new T [capacity]; } public Collection (ICollection items) { if (items == null) throw new ArgumentNullException ("items"); this.items = new T [items.Count]; items.CopyTo (this.items, 0); this.size = this.items.Length; } public void Add (T item) { if (size == items.Length) Grow (1); OnAdd (item, size); items [size++] = item; version++; } public bool Contains (T item) { return IndexOf (item) != -1; } public int IndexOf (T item) { return Array.IndexOf (items, item, 0, size); } public void Insert (int index, T item) { CheckIndex (index); if (size == items.Length) Grow (1); OnInsert (item, index); Shift (index, 1); items [index] = item; version++; } public void RemoveAt (int index) { if (index < 0 || index >= size) throw new ArgumentOutOfRangeException (); var item = items [index]; OnRemove (item, index); Shift (index, -1); Array.Clear (items, size, 1); version++; } public bool Remove (T item) { var index = IndexOf (item); if (index == -1) return false; OnRemove (item, index); Shift (index, -1); Array.Clear (items, size, 1); version++; return true; } public void Clear () { OnClear (); Array.Clear (items, 0, size); size = 0; version++; } public void CopyTo (T [] array, int arrayIndex) { Array.Copy (items, 0, array, arrayIndex, size); } public T [] ToArray () { var array = new T [size]; Array.Copy (items, 0, array, 0, size); return array; } void CheckIndex (int index) { if (index < 0 || index > size) throw new ArgumentOutOfRangeException (); } void Shift (int start, int delta) { if (delta < 0) start -= delta; if (start < size) Array.Copy (items, start, items, start + delta, size - start); size += delta; if (delta < 0) Array.Clear (items, size, -delta); } protected virtual void OnAdd (T item, int index) { } protected virtual void OnInsert (T item, int index) { } protected virtual void OnSet (T item, int index) { } protected virtual void OnRemove (T item, int index) { } protected virtual void OnClear () { } internal virtual void Grow (int desired) { int new_size = size + desired; if (new_size <= items.Length) return; const int default_capacity = 4; new_size = System.Math.Max ( System.Math.Max (items.Length * 2, default_capacity), new_size); #if !CF Array.Resize (ref items, new_size); #else var array = new T [new_size]; Array.Copy (items, array, size); items = array; #endif } int IList.Add (object value) { try { Add ((T) value); return size - 1; } catch (InvalidCastException) { } catch (NullReferenceException) { } throw new ArgumentException (); } void IList.Clear () { Clear (); } bool IList.Contains (object value) { return ((IList) this).IndexOf (value) > -1; } int IList.IndexOf (object value) { try { return IndexOf ((T) value); } catch (InvalidCastException) { } catch (NullReferenceException) { } return -1; } void IList.Insert (int index, object value) { CheckIndex (index); try { Insert (index, (T) value); return; } catch (InvalidCastException) { } catch (NullReferenceException) { } throw new ArgumentException (); } void IList.Remove (object value) { try { Remove ((T) value); } catch (InvalidCastException) { } catch (NullReferenceException) { } } void IList.RemoveAt (int index) { RemoveAt (index); } void ICollection.CopyTo (Array array, int index) { Array.Copy (items, 0, array, index, size); } public Enumerator GetEnumerator () { return new Enumerator (this); } IEnumerator IEnumerable.GetEnumerator () { return new Enumerator (this); } IEnumerator IEnumerable.GetEnumerator () { return new Enumerator (this); } public struct Enumerator : IEnumerator, IDisposable { Collection collection; T current; int next; readonly int version; public T Current { get { return current; } } object IEnumerator.Current { get { CheckState (); if (next <= 0) throw new InvalidOperationException (); return current; } } internal Enumerator (Collection collection) : this () { this.collection = collection; this.version = collection.version; } public bool MoveNext () { CheckState (); if (next < 0) return false; if (next < collection.size) { current = collection.items [next++]; return true; } next = -1; return false; } public void Reset () { CheckState (); next = 0; } void CheckState () { if (collection == null) throw new ObjectDisposedException (GetType ().FullName); if (version != collection.version) throw new InvalidOperationException (); } public void Dispose () { collection = null; } } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Collections.Generic/ReadOnlyCollection.cs ================================================ // // ReadOnlyCollection.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections; using System .Collections.Generic; namespace Mono.Collections.Generic { public sealed class ReadOnlyCollection : Collection, ICollection, IList { static ReadOnlyCollection empty; public static ReadOnlyCollection Empty { get { return empty ?? (empty = new ReadOnlyCollection ()); } } bool ICollection.IsReadOnly { get { return true; } } bool IList.IsFixedSize { get { return true; } } bool IList.IsReadOnly { get { return true; } } private ReadOnlyCollection () { } public ReadOnlyCollection (T [] array) { if (array == null) throw new ArgumentNullException (); Initialize (array, array.Length); } public ReadOnlyCollection (Collection collection) { if (collection == null) throw new ArgumentNullException (); Initialize (collection.items, collection.size); } void Initialize (T [] items, int size) { this.items = new T [size]; Array.Copy (items, 0, this.items, 0, size); this.size = size; } internal override void Grow (int desired) { throw new InvalidOperationException (); } protected override void OnAdd (T item, int index) { throw new InvalidOperationException (); } protected override void OnClear () { throw new InvalidOperationException (); } protected override void OnInsert (T item, int index) { throw new InvalidOperationException (); } protected override void OnRemove (T item, int index) { throw new InvalidOperationException (); } protected override void OnSet (T item, int index) { throw new InvalidOperationException (); } } } ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Security.Cryptography/CryptoConvert.cs ================================================ ================================================ FILE: ILRuntime/Mono.Cecil.20/MonoCecil/Mono.Security.Cryptography/CryptoService.cs ================================================ // // CryptoService.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.IO; using System.Reflection; using System.Security.Cryptography; ================================================ FILE: ILRuntime/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // 有关程序集的一般信息由以下 // 控制。更改这些特性值可修改 // 与程序集关联的信息。 [assembly: AssemblyTitle("ILRuntime")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("HP Inc.")] [assembly: AssemblyProduct("ILRuntime")] [assembly: AssemblyCopyright("Copyright © HP Inc. 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // 将 ComVisible 设置为 false 会使此程序集中的类型 //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 //请将此类型的 ComVisible 特性设置为 true。 [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID [assembly: Guid("eeb72dfc-0fa5-44de-b75a-586f69377aa7")] // 程序集的版本信息由下列四个值组成: // // 主版本 // 次版本 // 生成号 // 修订号 // // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 // 方法是按如下所示使用“*”: : // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: Libs/PublishLibrary.bat ================================================ set CurDir=%~dp0 set LibName=%1 echo LibName=%LibName% pdb2mdb %LibName%.dll xcopy %LibName%.dll %CurDir%..\..\SpiceUnity\SpiceUnity\LinkGameApp\Assets\Plugins\ManagedLibs\ /y xcopy %LibName%.dll.mdb %CurDir%..\..\SpiceUnity\SpiceUnity\LinkGameApp\Assets\Plugins\ManagedLibs\ /y ================================================ FILE: Libs/SGFAppDemo.exe.config ================================================ ================================================ FILE: Libs/SGFAppILRScript.dll.config ================================================ ================================================ FILE: Libs/SGFCore.dll.config ================================================ ================================================ FILE: README.md ================================================ # SGF the Smart Game Foundation QQ交流群:809637084 它主要由3个工程组成: * SGFCore:与Unity无关的功能模块。 * SGFUnity:与Unity相关的功能模块。 * SGFDebuger:一个日志输出工具。 其余工程说明: * ILRuntime:一个ILRuntime的第3方库。由于官方不推荐以DLL的形式用于项目中,所以该工程将不再维护。 * SGFServerLite:一个服务器的示例。 * SGFAppCommon/SGFAppILRScript/SGFAppDemo:一个客户端的综合演示示例,它包括与服务器通讯,热更新等等逻辑。 其余目录: * Libs:以上工程编译好的Dll,如果不需要修改代码的话,你可以直接使用这些Dll。 * Apps:以上示例编译好的Exe,你可以尝试运行一下,可能在不同的机器上运行会有问题,你最好直接打开对应的示例工程来调试运行。 其它: * SGF库发源于我的一个GAD课程项目:《贪吃蛇大作战》 * 其相关的视频链接为: * 第一季: http://gameinstitute.qq.com/lore/index/10007 * 第二季: http://gameinstitute.qq.com/lore/index/10017 ## 1.SGFCore ### Codec * 收集或者实现一些常用编解码库,或者对一些编解码库进行易用性封装。 * MiniJson,一个常用的轻量Json编解码库(Copyright (c) 2013 Calvin Rien) * PBSerializer,对Protobuf的封装,使之在一般场合下非常易用。 * SGFEncoding,一些自己实现的编解码相关算法,比如: * XOR * CheckSum * BytesToHex,HexToBytes * 等等 ### Common * 将来可能放一些数据结构相关的类,或者易用性封装。 * DictionarySafe,是对Dictionary做一个易用性封装。 * MapList,是将List与Dictionary结合起来做一个易用性封装。 ### Console * 控制台相关的功能。 * ConsoleInput:使控制台应用程序可以接受命令行输入。 ### Event * 事件系统。 * 它的思路与系统自带的Action类似,但是在性能与逻辑上比原生的Action更加可控,并且能够以日志的方式进行追踪和调试。 * 这在实际应用中非常有用。 ### G3Lite * 轻量级几何库。 * 考虑到很多时候需要脱离Unity进行开发,所以需要一套脱离Unity的几何类库。这里部分移植了geometry3Sharp里的一些基础类: - Vector2/Vector3/Vector4 - Matrix3 - Quaternion - MathUtil - IndexTypes ### IPCWork * 进程通讯模块。 * 它基于UdpSocket实现,以RPC的方式进行调用。 * 由于是基于Udp的简单实现,所以对单次通讯的数据大小有要求,不能超过当前系统的MTU。 * 如果需要在进程间进行大数据通讯,可以使用Network模块,建立可靠UDP连接,或者TCP连接。当然也可以采用共享内存和管道方案,期待后续有人来完善。 ### Marshals * 提供非托管相关的功能模块 * 利用它可以避开C#的内存管理,自己控制内存的分配和释放,避免GC - MarshalArray:参照托管Array来封装,使用方法上基本与Array相同 - MarshalList:参照托管List来封装,使用方法上基本与List相同 ### MathLite * 计划实现一套轻量级的数学库。 * 目前只有随机数生成算法。 ### Module * 模块管理器。 * 当项目的规模足够大时,就需要将整个系统划分为若干个模块。这些模块需要一套系统进行管理。 * 它具备很好的扩展性,结合ILRuntime可以实现iOS版本中模块级别的热更新。 * 它实现了模块间的消息通讯,并以此来解耦。 ### Network * 网络模块。 * 它实现了与网络通讯相关的绝大部分功能。 * Core,这里实现了一些数据、协议头、消息格式等的定义。还有一个轻量的RPC实现方案。 * FSPLite,实现了一个轻量级的【帧同步】通讯方案的前台与后台模块。使用它,你可以很快搭建出一个帧同步运行环境,包括帧同步服务器和客户端。 * General,实现了一个【通用】的网络通讯方案的前台与后台模块。使用它,你可以很容易实现游戏的状态同步,包括服务器和客户端。 ### Server * 服务器模块管理器。 * 在服务器开发中,当项目规范足够大时,也需要像客户端一样将整个系统划分为若干模块。这些模块需要进行管理。 * 目前该功能还比较简单,需要进一步完善。 ### Time * 与时间相关的类。 - SGFTime,类似Unity里的Time类。需要在App启动时,进行初始化。 ### Utils * 一些工具类。 - FileUtils,文件相关功能。 - PathUtils,路径相关功能。 - TimeUtils,时间相关功能。 - 等等 ## 2.SGFUnity ### DebugerGUI * 一个可扩展的运行时调试和测试工具GUI。 * 可以很方便地在其上扩展自己的工具页签。 ### ILR * 热更新相关的功能模块。 - DebugerILR,为热更模块提供日志输出功能。 - ModuleILR,支持模块级别的热更。 - UIILR,支持UI系统调用热更模块。 * 本热更方案可以实现在开发时,采用原生C#模式进行开发和单步调试。在发布时,无逢切换为热更模式。整个过程对于开发者是无感知的。 ### ILRuntime * 用于热更新的运行时库。因为需要支持IL2CPP的缘故,将直接使用其源代码,而非DLL。 * 于是,如果需要使用ILRuntime,你需要将SGFUnity这个库的源代码直接Copy到Unity工程中。 ### Mono.Cecil.20与Mono.Cecil.Pdb * 如果将SGFUnity以源代码的形式Copy到 Unity工程中,那么它们有可能与Unity新版本自带的库重复,如果这样的话,可以将其删除。 ### UI * UI系统。 * 这是一个基于UGUI的UI管理系统,封装了游戏开发中常用的几种UI元素。并且将这些元素分为2类,UIPage和UIPanel:页面。游戏的基础UI就是Page,它是全屏的。所有的游戏Panel都是显示在一个页面上的。 * 而UIPanel又可以分为以下几类: - UIWindow,游戏中的窗口。 - UILoading,游戏中的Loading。 - UIWidget,游戏中依附于窗口的一些小UI,或者会自动消失的小UI。 * 顺便封装了一些常用的通用UI面板和控件。 - UIMsgBox,继承自UIWindow。 - UIMsgTips,继承自UIWidget。 - UISimpleLoading,继承自UILoading。 - CtlList/CtlListItem - CtlProgressBar - 等等 ### Utils * 一些工具类。 ## 3.SGFDebuger * 一个日志工具类。 * 支持在非Unity环境和Unity环境下都能输出格式化日志。 * 并且支持日志保存为文件。 ================================================ FILE: SGF.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SGFCore", "SGFCore\SGFCore.csproj", "{EEB72DFC-0FA5-44DE-B75A-586F69377AA6}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SGFAppDemo", "SGFAppDemo\SGFAppDemo.csproj", "{3FACC3DD-FFA2-4FE7-B9B6-063260594AF1}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SGFUnity", "SGFUnity\SGFUnity.csproj", "{64ECFF78-EE1F-432B-A581-A70E8EB6DE83}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SGFDebuger", "SGFDebuger\SGFDebuger.csproj", "{DC1D8B0A-9C8C-4911-AAFE-D7D958EC4044}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SGFAppILRScript", "SGFAppILRScript\SGFAppILRScript.csproj", "{4704169C-4BAD-4CFB-842A-2F4E3FC60375}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SGFServerDemo", "SGFServerLite\SGFServerDemo.csproj", "{D1ACC88B-2B6E-43E5-8314-DD64C2F25AA7}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SGFAppCommon", "SGFAppCommon\SGFAppCommon.csproj", "{A1BF1B00-7CDF-4A48-8D33-98645E5DF606}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {EEB72DFC-0FA5-44DE-B75A-586F69377AA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EEB72DFC-0FA5-44DE-B75A-586F69377AA6}.Debug|Any CPU.Build.0 = Debug|Any CPU {EEB72DFC-0FA5-44DE-B75A-586F69377AA6}.Release|Any CPU.ActiveCfg = Release|Any CPU {EEB72DFC-0FA5-44DE-B75A-586F69377AA6}.Release|Any CPU.Build.0 = Release|Any CPU {3FACC3DD-FFA2-4FE7-B9B6-063260594AF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3FACC3DD-FFA2-4FE7-B9B6-063260594AF1}.Debug|Any CPU.Build.0 = Debug|Any CPU {3FACC3DD-FFA2-4FE7-B9B6-063260594AF1}.Release|Any CPU.ActiveCfg = Release|Any CPU {3FACC3DD-FFA2-4FE7-B9B6-063260594AF1}.Release|Any CPU.Build.0 = Release|Any CPU {64ECFF78-EE1F-432B-A581-A70E8EB6DE83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {64ECFF78-EE1F-432B-A581-A70E8EB6DE83}.Debug|Any CPU.Build.0 = Debug|Any CPU {64ECFF78-EE1F-432B-A581-A70E8EB6DE83}.Release|Any CPU.ActiveCfg = Release|Any CPU {64ECFF78-EE1F-432B-A581-A70E8EB6DE83}.Release|Any CPU.Build.0 = Release|Any CPU {DC1D8B0A-9C8C-4911-AAFE-D7D958EC4044}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DC1D8B0A-9C8C-4911-AAFE-D7D958EC4044}.Debug|Any CPU.Build.0 = Debug|Any CPU {DC1D8B0A-9C8C-4911-AAFE-D7D958EC4044}.Release|Any CPU.ActiveCfg = Release|Any CPU {DC1D8B0A-9C8C-4911-AAFE-D7D958EC4044}.Release|Any CPU.Build.0 = Release|Any CPU {4704169C-4BAD-4CFB-842A-2F4E3FC60375}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4704169C-4BAD-4CFB-842A-2F4E3FC60375}.Debug|Any CPU.Build.0 = Debug|Any CPU {4704169C-4BAD-4CFB-842A-2F4E3FC60375}.Release|Any CPU.ActiveCfg = Release|Any CPU {4704169C-4BAD-4CFB-842A-2F4E3FC60375}.Release|Any CPU.Build.0 = Release|Any CPU {D1ACC88B-2B6E-43E5-8314-DD64C2F25AA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D1ACC88B-2B6E-43E5-8314-DD64C2F25AA7}.Debug|Any CPU.Build.0 = Debug|Any CPU {D1ACC88B-2B6E-43E5-8314-DD64C2F25AA7}.Release|Any CPU.ActiveCfg = Release|Any CPU {D1ACC88B-2B6E-43E5-8314-DD64C2F25AA7}.Release|Any CPU.Build.0 = Release|Any CPU {A1BF1B00-7CDF-4A48-8D33-98645E5DF606}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A1BF1B00-7CDF-4A48-8D33-98645E5DF606}.Debug|Any CPU.Build.0 = Debug|Any CPU {A1BF1B00-7CDF-4A48-8D33-98645E5DF606}.Release|Any CPU.ActiveCfg = Release|Any CPU {A1BF1B00-7CDF-4A48-8D33-98645E5DF606}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {03B7BAC5-A958-46AB-9392-318A99832A01} EndGlobalSection EndGlobal ================================================ FILE: SGFAppCommon/Data/PlayerData.cs ================================================ using ProtoBuf; namespace SGFAppDemo.Common.Data { [ProtoContract] public class PlayerData { [ProtoMember(1)] public uint id; [ProtoMember(2)] public string name; [ProtoMember(3)] public uint userId; [ProtoMember(4)] public uint sid; [ProtoMember(5)] public bool isReady; public override string ToString () { return string.Format ("", id, name, userId, sid, isReady); } } } ================================================ FILE: SGFAppCommon/Data/RoomData.cs ================================================ using System; using System.Collections.Generic; using System.Text; using ProtoBuf; using SGF.Extension; namespace SGFAppDemo.Common.Data { [ProtoContract] public class RoomData { [ProtoMember(1)] public uint id; [ProtoMember(2)] public string name; [ProtoMember(3)] public uint owner; [ProtoMember(4)] public List players = new List(); public override string ToString() { return string.Format("",id,name,owner,players.ToListString()); } } [ProtoContract] public class RoomListData { [ProtoMember(1)] public List rooms = new List(); } } ================================================ FILE: SGFAppCommon/Data/UserData.cs ================================================ using ProtoBuf; using SGF.Utils; namespace SGFAppDemo.Common.Data { [ProtoContract] public class UserData { public static int OnlineTimeout = 40; [ProtoMember(1)] public uint id; [ProtoMember(2)] public string name; [ProtoMember(3)] public string pwd; public UserServerData svrdata = new UserServerData(); public override string ToString() { return string.Format("", id, name, svrdata.online); } } public class UserServerData { public uint lastHeartBeatTime = 0; private bool m_online = false; public bool online { get { if (m_online) { uint dt = (uint)TimeUtils.GetTotalSecondsSince1970() - lastHeartBeatTime; if (dt > UserData.OnlineTimeout) { m_online = false; } } return m_online; } set { m_online = value; } } } } ================================================ FILE: SGFAppCommon/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // 有关程序集的一般信息由以下 // 控制。更改这些特性值可修改 // 与程序集关联的信息。 [assembly: AssemblyTitle("SGFAppCommon")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Microsoft")] [assembly: AssemblyProduct("SGFAppCommon")] [assembly: AssemblyCopyright("Copyright © Microsoft 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] //将 ComVisible 设置为 false 将使此程序集中的类型 //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, //请将此类型的 ComVisible 特性设置为 true。 [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID [assembly: Guid("dc1d8b0a-9c8c-4911-aafe-d7d958ec4045")] // 程序集的版本信息由下列四个值组成: // // 主版本 // 次版本 // 生成号 // 修订号 // //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, // 方法是按如下所示使用“*”: : // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: SGFAppCommon/Proto/HeartBeatProto.cs ================================================ using ProtoBuf; using SGF.Network.General.Proto; using SGFAppDemo.Common.Data; namespace SGFAppDemo.Common.Proto { /// /// 可以利用心跳协议完成网络测速 /// [ProtoContract] public class HeartBeatReq { [ProtoMember(1)] public ushort ping; [ProtoMember(2)] public uint timestamp; } [ProtoContract] public class HeartBeatRsp { [ProtoMember(1)]public ReturnCode ret; [ProtoMember(2)]public uint timestamp; } } ================================================ FILE: SGFAppCommon/Proto/LoginProto.cs ================================================ using ProtoBuf; using SGF.Network.General.Proto; using SGFAppDemo.Common.Data; namespace SGFAppDemo.Common.Proto { [ProtoContract] public class LoginReq { [ProtoMember(1)] public uint id; [ProtoMember(2)] public string name; } [ProtoContract] public class LoginRsp { [ProtoMember(1)] public ReturnCode ret; [ProtoMember(2)] public UserData userdata; } } ================================================ FILE: SGFAppCommon/Proto/ProtoCmd.cs ================================================ using ProtoBuf; namespace SGFAppDemo.Common.Proto { public class ProtoCmd { public static uint LoginReq = 1; public static uint LoginRsp = 2; public static uint HeartBeatReq = 3; public static uint HeartBeatRsp = 4; } } ================================================ FILE: SGFAppCommon/SGFAppCommon.csproj ================================================  Debug AnyCPU {A1BF1B00-7CDF-4A48-8D33-98645E5DF606} Library Properties SGFAppDemo.Common SGFAppCommon v3.5 512 true full false ..\Libs\ TRACE;DEBUG;ENABLE_LOG;ENABLE_LOG_LOOP prompt 4 pdbonly true ..\Libs\ TRACE;ENABLE_LOG;ENABLE_LOG_LOOP prompt 4 False ..\Libs\Common\protobuf-net.dll {eeb72dfc-0fa5-44de-b75a-586f69377aa6} SGFCore $(ProjectDir)..\Libs\PublishLibrary.bat $(TargetName) ================================================ FILE: SGFAppDemo/App.config ================================================ ================================================ FILE: SGFAppDemo/AppMain.cs ================================================  using System; using SGF; using SGF.Module; using SGF.Unity.ILR; using SGF.Unity.ILR.ModuleILR; using SGFAppDemo.Framework; using SGFAppDemo.Services; namespace SGFAppDemo { public class AppMain:SGFGameObject { public override void Active() { InitServices(); UpdateVersion(); } private void InitServices() { Debuger.Log(); ILRManager.Instance.Init(RunMode.Native, false); ILRManager.Instance.AddSearchDirectory(AppDomain.CurrentDomain.BaseDirectory); ILRManager.Instance.LoadAssembly(ModuleDef.ScriptAssemblyName); ModuleManager.Instance.Init(); ModuleManager.Instance.RegisterModuleActivator(new NativeModuleActivator(ModuleDef.Namespace, ModuleDef.NativeAssemblyName)); ModuleManager.Instance.RegisterModuleActivator(new ILRModuleActivator(ModuleDef.Namespace, ModuleDef.ScriptAssemblyName)); OnlineManager.Instance.Init(); } private void UpdateVersion() { ModuleManager.Instance.CreateModule(ModuleDef.VersionModule); ModuleManager.Instance.ShowModule(ModuleDef.VersionModule); GlobalEvent.onVersionUpdateComplete.AddListener(OnVersionUpdateComplete); } private void OnVersionUpdateComplete() { GlobalEvent.onVersionUpdateComplete.RemoveAllListeners(); //由脚本来初始业务逻辑,便于热更 bool ret = (bool)ILRManager.Instance.Invoke("SGFAppDemo.ScriptMain", "Init"); if (!ret) { Debuger.LogError("初始化业务逻辑失败!"); Console.WriteLine("初始化业务逻辑失败!"); } } } } ================================================ FILE: SGFAppDemo/Framework/SGFGameDefine.cs ================================================ namespace SGFAppDemo.Framework { public static class SGFGameDefine { public static int FPS = 30; public static int FRAME_TICK_INTERVAL{get { return (int)(FRAME_INTERVAL * 10000); } } public static float FRAME_INTERVAL { get { return 1000 / FPS; } } } } ================================================ FILE: SGFAppDemo/Framework/SGFGameMainLoop.cs ================================================ using System; using SGF; using SGF.Utils; namespace SGFAppDemo.Framework { public class SGFGameMainLoop { private static bool m_run = false; public static void Run() { float deltaTimeMS = 0; long m_LogicLastTicks = DateTime.Now.Ticks; long nowticks = DateTime.Now.Ticks; long interval = 0; long fixedFrameInterval = 0; ConsoleInput.onInputKey.AddListener(OnInputKey); m_run = true; while (m_run) { ConsoleInput.Tick(); fixedFrameInterval = SGFGameDefine.FRAME_TICK_INTERVAL; nowticks = DateTime.Now.Ticks; interval = nowticks - m_LogicLastTicks; if (interval >= fixedFrameInterval) { deltaTimeMS = interval / 10000.0f; SGFGameObject[] list; int cnt = 0; while (interval >= fixedFrameInterval) { interval -= fixedFrameInterval; list = SGFGameObject.GetActivedGameObjects(); cnt = list.Length; for (int i = 0; i < cnt; i++) { list[i].FixedUpdate(); } GlobalEvent.onFixedUpdate.Invoke(); } list = SGFGameObject.GetActivedGameObjects(); cnt = list.Length; for (int i = 0; i < cnt; i++) { list[i].Update(deltaTimeMS); } GlobalEvent.onUpdate.Invoke(deltaTimeMS); m_LogicLastTicks = nowticks - interval; } } } private static void OnInputKey(ConsoleKey key) { if (key == ConsoleKey.Escape) { m_run = false; } } } } ================================================ FILE: SGFAppDemo/Framework/SGFGameObject.cs ================================================ using System; using System.Collections.Generic; namespace SGFAppDemo.Framework { public class SGFGameObject { private static List m_listInstancedObject = new List(); private static List m_listActivedObject = new List(); public static SGFGameObject Instance(Type type) { if (type.IsSubclassOf(typeof(SGFGameObject))) { SGFGameObject obj = Activator.CreateInstance(type) as SGFGameObject; obj.InstanceInternal(); return obj; } return null; } public static void Destroy(SGFGameObject obj) { obj.DestroyInternal(); } public static SGFGameObject[] GetActivedGameObjects() { return m_listActivedObject.ToArray(); } public static SGFGameObject[] GetInstancedGameObjects() { return m_listInstancedObject.ToArray(); } public static void DestroyAll() { SGFGameObject[] list = m_listInstancedObject.ToArray(); int cnt = list.Length; for (int i = 0; i < cnt; i++) { list[i].DestroyInternal(); } m_listInstancedObject.Clear(); } private bool m_instanced = false; private bool m_actived = false; protected SGFGameObject() { InstanceInternal(); } private void InstanceInternal() { if (!m_instanced) { m_instanced = true; m_listInstancedObject.Add(this); Instance(); SetActive(true); } } private void DestroyInternal() { if (m_instanced) { if (m_actived) { m_actived = false; m_listActivedObject.Remove(this); Deactive(); } m_instanced = false; m_listInstancedObject.Remove(this); Destroy(); } } public virtual void Instance() { } public virtual void Destroy() { DestroyInternal(); } public void SetActive(bool value) { if (m_actived != value) { m_actived = value; if (m_actived) { if (!m_listActivedObject.Contains(this)) { m_listActivedObject.Add(this); } Active(); } else { m_listActivedObject.Remove(this); Deactive(); } } } public virtual void Active() { } public virtual void Deactive() { } public virtual void Update(float deltaTime) { } public virtual void FixedUpdate() { } } } ================================================ FILE: SGFAppDemo/GlobalEvent.cs ================================================ using SGF.SEvent; namespace SGFAppDemo { /// /// 全局事件 /// 有些事件不确定应该是由谁发出 /// 就可以通过全局事件来收和发 /// public static class GlobalEvent { public static Signal onVersionUpdateComplete = new Signal(); public static Signal onFixedUpdate = new Signal(); public static Signal onUpdate = new Signal(); } } ================================================ FILE: SGFAppDemo/ModuleDef.cs ================================================ namespace SGFAppDemo { internal static class ModuleDef { public const string Namespace = "SGFAppDemo.Modules"; public const string NativeAssemblyName = "SGFAppDemo"; public const string ScriptAssemblyName = "SGFAppILRScript"; public const string VersionModule = "VersionModule"; } } ================================================ FILE: SGFAppDemo/Modules/Version/VersionModule.cs ================================================ using System; using SGF; using SGF.Module; using SGF.Time; namespace SGFAppDemo.Modules { public class VersionModule : GeneralModule { private float m_progress = 0; protected override void Show(object arg) { base.Show(arg); GlobalEvent.onUpdate.AddListener(OnUpdate); } private void OnUpdate(float deltaTime) { m_progress += 0.1f; if (m_progress > 1) { m_progress = 1; } Console.Write("模拟版本更新:" + (int)(m_progress * 100) + "%\r"); if (m_progress >= 1) { Console.WriteLine(); GlobalEvent.onUpdate.RemoveListener(OnUpdate); GlobalEvent.onVersionUpdateComplete.Invoke(); } } } } ================================================ FILE: SGFAppDemo/Program.cs ================================================  using System; using SGF; using SGF.Time; using SGFAppDemo.Framework; namespace SGFAppDemo { class Program { static void Main(string[] args) { InitDebuger(); SGFTime.DateTimeAppStart = DateTime.Now; SGFGameObject.Instance(typeof(AppMain)); SGFGameMainLoop.Run(); SGFGameObject.DestroyAll(); Console.WriteLine("GameOver"); Console.ReadKey(); } private static void InitDebuger() { Debuger.Init(); Debuger.EnableLog = true; Debuger.EnableSave = true; Debuger.Log(); } } } ================================================ FILE: SGFAppDemo/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // 有关程序集的一般信息由以下 // 控制。更改这些特性值可修改 // 与程序集关联的信息。 [assembly: AssemblyTitle("SGFAppDemo")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("HP Inc.")] [assembly: AssemblyProduct("SGFAppDemo")] [assembly: AssemblyCopyright("Copyright © HP Inc. 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // 将 ComVisible 设置为 false 会使此程序集中的类型 //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 //请将此类型的 ComVisible 特性设置为 true。 [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID [assembly: Guid("3facc3dd-ffa2-4fe7-b9b6-063260594af1")] // 程序集的版本信息由下列四个值组成: // // 主版本 // 次版本 // 生成号 // 修订号 // // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 // 方法是按如下所示使用“*”: : // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: SGFAppDemo/SGFAppDemo.csproj ================================================  Debug AnyCPU {3FACC3DD-FFA2-4FE7-B9B6-063260594AF1} Exe SGFAppDemo SGFAppDemo v3.5 512 true AnyCPU true full false ..\Apps\ TRACE;DEBUG;ENABLE_LOG prompt 4 AnyCPU pdbonly true ..\Apps\ TRACE;ENABLE_LOG prompt 4 False ..\Libs\ILRuntime.dll False ..\Libs\SGFDebuger.dll {a1bf1b00-7cdf-4a48-8d33-98645e5df606} SGFAppCommon {eeb72dfc-0fa5-44de-b75a-586f69377aa6} SGFCore {64ecff78-ee1f-432b-a581-a70e8eb6de83} SGFUnity ================================================ FILE: SGFAppDemo/SGFGameDefine.cs ================================================ namespace SGFAppDemo { public static class SGFGameDefine { public static int FPS = 30; public static int FRAME_TICK_INTERVAL{get { return (int)(FRAME_INTERVAL * 10000); } } public static float FRAME_INTERVAL { get { return 1000 / FPS; } } } } ================================================ FILE: SGFAppDemo/SGFGameMainLoop.cs ================================================ using System; using SGF; using SGF.Time; namespace SGFAppDemo { public class SGFGameMainLoop { public static void Run() { float deltaTimeMS = 0; long m_LogicLastTicks = DateTime.Now.Ticks; long nowticks = DateTime.Now.Ticks; long interval = 0; long fixedFrameInterval = 0; while (true) { if (Console.KeyAvailable) { ConsoleKeyInfo info = Console.ReadKey(); if (info.Key == ConsoleKey.Escape) { break; } } fixedFrameInterval = SGFGameDefine.FRAME_TICK_INTERVAL; nowticks = DateTime.Now.Ticks; interval = nowticks - m_LogicLastTicks; if (interval >= fixedFrameInterval) { deltaTimeMS = interval / 10000.0f; SGFGameObject[] list; int cnt = 0; while (interval >= fixedFrameInterval) { interval -= fixedFrameInterval; list = SGFGameObject.GetActivedGameObjects(); cnt = list.Length; for (int i = 0; i < cnt; i++) { list[i].FixedUpdate(); } GlobalEvent.onFixedUpdate.Invoke(); } list = SGFGameObject.GetActivedGameObjects(); cnt = list.Length; for (int i = 0; i < cnt; i++) { list[i].Update(deltaTimeMS); } GlobalEvent.onUpdate.Invoke(deltaTimeMS); m_LogicLastTicks = nowticks - interval; } } } } } ================================================ FILE: SGFAppDemo/SGFGameObject.cs ================================================ using System; using System.Collections.Generic; namespace SGFAppDemo { public class SGFGameObject { private static List m_listInstancedObject = new List(); private static List m_listActivedObject = new List(); public static SGFGameObject Instance(Type type) { if (type.IsSubclassOf(typeof(SGFGameObject))) { SGFGameObject obj = Activator.CreateInstance(type) as SGFGameObject; obj.InstanceInternal(); return obj; } return null; } public static void Destroy(SGFGameObject obj) { obj.DestroyInternal(); } public static SGFGameObject[] GetActivedGameObjects() { return m_listActivedObject.ToArray(); } public static SGFGameObject[] GetInstancedGameObjects() { return m_listInstancedObject.ToArray(); } public static void DestroyAll() { SGFGameObject[] list = m_listInstancedObject.ToArray(); int cnt = list.Length; for (int i = 0; i < cnt; i++) { list[i].DestroyInternal(); } m_listInstancedObject.Clear(); } private bool m_instanced = false; private bool m_actived = false; protected SGFGameObject() { InstanceInternal(); } private void InstanceInternal() { if (!m_instanced) { m_instanced = true; m_listInstancedObject.Add(this); Instance(); SetActive(true); } } private void DestroyInternal() { if (m_instanced) { if (m_actived) { m_actived = false; m_listActivedObject.Remove(this); Deactive(); } m_instanced = false; m_listInstancedObject.Remove(this); Destroy(); } } public virtual void Instance() { } public virtual void Destroy() { DestroyInternal(); } public void SetActive(bool value) { if (m_actived != value) { m_actived = value; if (m_actived) { if (!m_listActivedObject.Contains(this)) { m_listActivedObject.Add(this); } Active(); } else { m_listActivedObject.Remove(this); Deactive(); } } } public virtual void Active() { } public virtual void Deactive() { } public virtual void Update(float deltaTime) { } public virtual void FixedUpdate() { } } } ================================================ FILE: SGFAppDemo/Services/Online/HeartBeatHandler.cs ================================================ using SGF; using SGF.MathLite; using SGF.Network.Core; using SGF.Network.General.Client; using SGF.SEvent; using SGF.Time; using SGF.Utils; using SGFAppDemo.Common.Proto; namespace SGFAppDemo.Services.Online { public class HeartBeatHandler { private NetManager m_net; public Signal onTimeout = new Signal(); private float m_lastHeartBeatTime = 0; private uint m_ping = 0; public void Init(NetManager net) { m_net = net; } public void Start() { m_lastHeartBeatTime = SGFTime.GetTimeSinceStartup() + SGFRandom.Default.Range(5.0f); GlobalEvent.onUpdate.AddListener(OnUpdate); } public void Stop() { GlobalEvent.onUpdate.RemoveListener(OnUpdate); } private void OnUpdate(float dt) { float current = SGFTime.GetTimeSinceStartup(); if (current - m_lastHeartBeatTime > 5.0f) { m_lastHeartBeatTime = current; HeartBeatReq req = new HeartBeatReq(); req.ping = (ushort)m_ping; req.timestamp = (uint)TimeUtils.GetTotalMillisecondsSince1970(); //m_net.Send(ProtoCmd.HeartBeatReq, req, OnHeartBeatRsp,15, OnHeartBeatError); m_net.Send(ProtoCmd.HeartBeatReq, req, OnHeartBeatRsp, 15, OnHeartBeatError); } } private void OnHeartBeatRsp(uint index, HeartBeatRsp rsp) { Debuger.Log(); if (rsp.ret.code == 0) { uint current = (uint)TimeUtils.GetTotalMillisecondsSince1970(); uint dt = current - rsp.timestamp; m_ping = dt / 2; } } private void OnHeartBeatError(NetErrorCode code) { if (code == NetErrorCode.Timeout) { Stop(); onTimeout.Invoke(); } } } } ================================================ FILE: SGFAppDemo/Services/Online/OnlineManager.cs ================================================ using System; using System.Collections.Generic; using SGF; using SGF.Extension; using SGF.Module; using SGF.Network.Core; using SGF.Network.Core.RPCLite; using SGF.Network.General; using SGF.Network.General.Client; using SGF.Time; using SGF.Utils; using SGFAppDemo.Common.Data; using SGFAppDemo.Common.Proto; using SGFAppDemo.Services.Online; namespace SGFAppDemo.Services { public enum ConnID { ZoneServer = 1, GameServer = 2 } public class OnlineManager:Singleton { private NetManager m_net; private bool m_connected = false; private UserData m_mainUserData = null; private HeartBeatHandler m_heartbeat; public void Init() { m_net = new NetManager(); //m_net.Init(typeof(KCPConnection), (int)ConnID.ZoneServer,0); //m_net.RegisterRPCListener(this); m_net.Init(ConnectionType.RUDP, 0); m_net.Rpc.RegisterListener(this); GlobalEvent.onUpdate.AddListener(OnUpdate); ConsoleInput.onInputKey.AddListener(OnInputKey); m_heartbeat = new HeartBeatHandler(); m_heartbeat.Init(m_net); m_heartbeat.onTimeout.AddListener(OnHeartBeatTimeout); } private void OnInputKey(ConsoleKey key) { Debuger.Log(key); if (key == ConsoleKey.F1) { m_net.Dump(); ServerProfiler.Init(); } else if(key == ConsoleKey.F2) { ServerProfiler.Start(); Login("slicol"); } else if (key == ConsoleKey.F3) { ServerProfiler.Stop(); Logout(); } } public NetManager Net { get { return m_net; }} public UserData MainUserData { get { return m_mainUserData; } } private void OnUpdate(float dt) { m_net.Tick(); } private void OnHeartBeatTimeout() { Debuger.LogWarning(""); CloseConnect(); m_heartbeat.Stop(); //转个菊花 //执行断线重连策略 ReLogin(); } public void Connect() { if (!m_connected) { m_net.Connect("111.230.116.185", 4540); //m_net.Connect("127.0.0.1", 4540); //m_connected = m_net.Connected; m_connected = m_net.IsConnected; } } private void CloseConnect() { m_net.Close(); m_connected = false; } public void Login(string username) { Connect(); LoginReq req = new LoginReq(); req.name = username; req.id = 0; //m_net.Send(ProtoCmd.LoginReq, req, OnLoginRsp); m_net.Send(ProtoCmd.LoginReq, req, OnLoginRsp); } private void ReLogin() { Connect(); LoginReq req = new LoginReq(); req.name = m_mainUserData.name; req.id = m_mainUserData.id; //m_net.Send(ProtoCmd.LoginReq, req, OnLoginRsp); m_net.Send(ProtoCmd.LoginReq, req, OnLoginRsp); } private void OnLoginRsp(uint index, LoginRsp rsp) { if (rsp.ret.code == 0) { Debuger.Log("UserData:{0}", rsp.userdata); m_mainUserData = rsp.userdata; m_heartbeat.Start(); } else { Debuger.LogWarning(rsp.ret.info); } } public void Logout() { m_heartbeat.Stop(); if (m_mainUserData != null) { //m_net.Invoke("Logout"); m_net.Rpc.Invoke("Logout"); } m_mainUserData = null; } [RPCResponse] private void OnLogout() { m_connected = false; } } } ================================================ FILE: SGFAppDemo/Services/Online/ServerProfiler.cs ================================================ using System.Collections.Generic; namespace SGFAppDemo.Services.Online { public class ServerProfiler { private static List m_listBot = new List(); private static bool m_start = false; private static bool m_inited = false; public static void Init() { if (m_inited) { return; } m_inited = true; GlobalEvent.onUpdate.AddListener(OnUpdate); if (m_listBot.Count == 0) { for (int i = 0; i < 1000; i++) { var bot = new ServerTestBot(); m_listBot.Add(bot); bot.Init(); } } } public static void Start() { if (!m_inited) { return; } if (m_start) { return; } m_start = true; for (int i = 0; i < m_listBot.Count; i++) { m_listBot[i].Login("TestName#" + i); } } public static void Stop() { if (!m_inited) { return; } if (!m_start) { return; } m_start = false; for (int i = 0; i < m_listBot.Count; i++) { m_listBot[i].Logout(); } } private static void OnUpdate(float dt) { if (!m_inited) { return; } for (int i = 0; i < m_listBot.Count; i++) { m_listBot[i].Update(); } } } } ================================================ FILE: SGFAppDemo/Services/Online/ServerTestBot.cs ================================================ using SGF; using SGF.Extension; using SGF.Network.General; using SGF.Network.General.Client; using SGFAppDemo.Common.Data; using SGFAppDemo.Common.Proto; namespace SGFAppDemo.Services.Online { public class ServerTestBot { private NetManager m_net; private bool m_connected = false; private UserData m_mainUserData = null; private HeartBeatHandler m_heartbeat; public void Init() { m_net = new NetManager(); //m_net.Init(typeof(KcpConnection), (int)ConnID.ZoneServer,0); //m_net.RegisterRPCListener(this); m_net.Init(ConnectionType.RUDP, 0); m_net.Rpc.RegisterListener(this); m_heartbeat = new HeartBeatHandler(); m_heartbeat.Init(m_net); } public void Connect() { if (!m_connected) { m_net.Connect("111.230.116.185", 4540); //m_net.Connect("127.0.0.1", 4540); //m_connected = m_net.Connected; m_connected = m_net.IsConnected; } } public void Update() { m_net.Tick(); } public void Login(string username) { Connect(); LoginReq req = new LoginReq(); req.name = username; //m_net.Send(ProtoCmd.LoginReq, req, OnLoginRsp); m_net.Send(ProtoCmd.LoginReq, req, OnLoginRsp); } public void Logout() { m_heartbeat.Stop(); if (m_mainUserData != null) { //m_net.Invoke("Logout"); m_net.Rpc.Invoke("Logout"); } m_mainUserData = null; } private void OnLogout() { Debuger.Log(); } private void OnLoginRsp(uint index, LoginRsp rsp) { if (rsp.ret.code == 0) { Debuger.Log("UserData:{0}", rsp.userdata); m_mainUserData = rsp.userdata; m_heartbeat.Start(); } else { Debuger.LogWarning(rsp.ret.info); } } } } ================================================ FILE: SGFAppILRScript/App.config ================================================ ================================================ FILE: SGFAppILRScript/ModuleDef.cs ================================================ namespace SGFAppDemo { internal static class ModuleDef { public const string LoginModule = "LoginModule"; public const string HomeModule = "HomeModule"; public const string RoomModule = "RoomModule"; public const string SettingModule = "SettingModule"; public const string ActivityModule = "ActivityModule"; public const string DailyCheckInModule = "DailyCheckInModule"; public const string ShopModule = "ShopModule"; public const string ShareModule = "ShareModule"; public const string PVEModule = "PVEModule"; public const string PVPModule = "PVPModule"; } } ================================================ FILE: SGFAppILRScript/Modules/Login/LoginModule.cs ================================================ using System; using SGF; using SGF.Module; using SGF.Unity.Common; using SGF.Utils; using SGFAppDemo.Services; namespace SGFAppDemo.Modules { public class LoginModule : GeneralModule { protected override void Show(object arg) { base.Show(arg); Debuger.Log("显示登录界面!(模拟一下)"); Console.WriteLine("输入命令进行操作"); Console.WriteLine("命令格式:Login %username%"); Console.WriteLine("命令格式:Logout"); Console.WriteLine("命令格式:ShowRoom"); ConsoleInput.onInputLine.AddListener(OnInputLine); } private void OnInputLine(string line) { if (line.StartsWith("Login")) { string[] args = line.Split(' '); if (args.Length > 1) { string username = args[1]; OnlineManager.Instance.Login(username); } else { Debuger.LogError("输入格式错误!"); } } else if (line == "Logout") { OnlineManager.Instance.Logout(); } else if (line == "ShowRoom") { ModuleManager.Instance.ShowModule(ModuleDef.RoomModule); } } } } ================================================ FILE: SGFAppILRScript/Modules/Room/RoomModule.cs ================================================ using System; using System.Collections.Generic; using SGF; using SGF.Extension; using SGF.Module; using SGF.Network.Core; using SGF.Network.Core.RPCLite; using SGF.Network.FSPLite; using SGF.Utils; using SGFAppDemo.Common.Data; using SGFAppDemo.Services; namespace SGFAppDemo.Modules { public class RoomModule : GeneralModule { private List m_listRoom = null; private RoomData m_currRoom = new RoomData(); protected override void Show(object arg) { base.Show(arg); Debuger.Log("显示房间界面!(模拟一下)"); Debuger.Log("显示登录界面!(模拟一下)"); Console.WriteLine("输入命令进行操作"); Console.WriteLine("命令格式:ShowRoomList"); Console.WriteLine("命令格式:CreateRoom %roomname%"); Console.WriteLine("命令格式:JoinRoom %roomid%"); Console.WriteLine("命令格式:ExitRoom"); Console.WriteLine("命令格式:RoomReady %ready%"); ConsoleInput.onInputLine.AddListener(OnInputLine); OnlineManager.Instance.Net.Rpc.RegisterListener(this); } private void OnInputLine(string line) { if (line == "ShowRoomList") { OnlineManager.Instance.Net.Rpc.Invoke("GetRoomList"); } else if(line.StartsWith("CreateRoom")) { string[] args = line.Split(' '); if (args.Length > 1) { UserData ud = OnlineManager.Instance.MainUserData; string name = args[1]; OnlineManager.Instance.Net.Rpc.Invoke("CreateRoom", ud.id, name); } else { Debuger.LogError("输入格式错误!"); } } else if (line.StartsWith("JoinRoom")) { string[] args = line.Split(' '); if (args.Length > 1) { UserData ud = OnlineManager.Instance.MainUserData; uint id = uint.Parse(args[1]); OnlineManager.Instance.Net.Rpc.Invoke("JoinRoom", ud.id, id); } else { Debuger.LogError("输入格式错误!"); } } else if (line == "ExitRoom") { UserData ud = OnlineManager.Instance.MainUserData; OnlineManager.Instance.Net.Rpc.Invoke("ExitRoom", ud.id, m_currRoom.id); } else if (line.StartsWith("RoomReady")) { string[] args = line.Split(' '); if (args.Length > 1) { bool ready = args[1] == "true"; UserData ud = OnlineManager.Instance.MainUserData; OnlineManager.Instance.Net.Rpc.Invoke("RoomReady", ud.id, m_currRoom.id, ready); } else { Debuger.LogError("输入格式错误!"); } } else if (line == "StartGame") { UserData ud = OnlineManager.Instance.MainUserData; OnlineManager.Instance.Net.Rpc.Invoke("StartGame", ud.id, m_currRoom.id); } } [RPCResponse] private void OnGetRoomList(RoomListData data) { if (data != null) { m_listRoom = data.rooms; for (int i = 0; i < m_listRoom.Count; i++) { Debuger.LogWarning(m_listRoom[i].ToString()); } } else { Debuger.LogWarning("房间列表为空!"); } } [RPCResponse] private void OnCreateRoom(RoomData data) { Debuger.Log(data.ToString()); m_currRoom = data; } [RPCResponse] private void OnJoinRoom(RoomData data) { Debuger.Log(data.ToString()); m_currRoom = data; } [RPCNotify] private void NotifyRoomUpdate(RoomData data) { Debuger.Log(data.ToString()); m_currRoom = data; } [RPCNotify] private void NotifyGameStart(FSPParam param) { Debuger.LogWarning(param.ToString()); } } } ================================================ FILE: SGFAppILRScript/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // 有关程序集的一般信息由以下 // 控制。更改这些特性值可修改 // 与程序集关联的信息。 [assembly: AssemblyTitle("SGFAppILRScript")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("HP Inc.")] [assembly: AssemblyProduct("SGFAppILRScript")] [assembly: AssemblyCopyright("Copyright © HP Inc. 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // 将 ComVisible 设置为 false 会使此程序集中的类型 //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 //请将此类型的 ComVisible 特性设置为 true。 [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID [assembly: Guid("eeb72dfc-0fa5-44de-b75a-586f69377aa8")] // 程序集的版本信息由下列四个值组成: // // 主版本 // 次版本 // 生成号 // 修订号 // // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 // 方法是按如下所示使用“*”: : // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: SGFAppILRScript/SGFAppILRScript.csproj ================================================  Debug AnyCPU {4704169C-4BAD-4CFB-842A-2F4E3FC60375} Library SGFAppDemo SGFAppILRScript v3.5 512 true AnyCPU true full false ..\Apps\ TRACE;DEBUG;ENABLE_LOG prompt 0 false true AnyCPU pdbonly true ..\Apps\ TRACE;ENABLE_LOG prompt 0 false true False ..\Libs\ILRuntime.dll False ..\Libs\protobuf-net.dll False ..\Libs\SGFCore.dll False ..\Libs\SGFDebuger.dll False ..\Libs\SGFUnity.dll {a1bf1b00-7cdf-4a48-8d33-98645e5df606} SGFAppCommon {3facc3dd-ffa2-4fe7-b9b6-063260594af1} SGFAppDemo ================================================ FILE: SGFAppILRScript/SGFAppILRScript.csproj.user ================================================  ProjectFiles ================================================ FILE: SGFAppILRScript/ScriptMain.cs ================================================  using System; using SGF; using SGF.Module; namespace SGFAppDemo { public class ScriptMain { public static bool Init() { Debuger.Log(); ModuleManager.Instance.CreateModule(ModuleDef.LoginModule); ModuleManager.Instance.CreateModule(ModuleDef.RoomModule); ModuleManager.Instance.ShowModule(ModuleDef.LoginModule); return true; } } } ================================================ FILE: SGFCore/App.config ================================================ ================================================ FILE: SGFCore/Class1.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace SGFCore { public class Class1 { } } ================================================ FILE: SGFCore/Codec/MiniJSON.cs ================================================ /* * Copyright (c) 2013 Calvin Rien * * Based on the JSON parser by Patrick van Bergen * http://techblog.procurios.nl/k/618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html * * Simplified it so that it doesn't throw exceptions * and can be used in Unity iPhone with maximum code stripping. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Text; namespace MiniJSON.Safe { // Example usage: // // using UnityEngine; // using System.Collections; // using System.Collections.Generic; // using MiniJSON; // // public class MiniJSONTest : MonoBehaviour { // void Start () { // var jsonString = "{ \"array\": [1.44,2,3], " + // "\"object\": {\"key1\":\"value1\", \"key2\":256}, " + // "\"string\": \"The quick brown fox \\\"jumps\\\" over the lazy dog \", " + // "\"unicode\": \"\\u3041 Men\u00fa sesi\u00f3n\", " + // "\"int\": 65536, " + // "\"float\": 3.1415926, " + // "\"bool\": true, " + // "\"null\": null }"; // // var dict = Json.Deserialize(jsonString) as Dictionary; // // Debug.Log("deserialized: " + dict.GetType()); // Debug.Log("dict['array'][0]: " + ((List) dict["array"])[0]); // Debug.Log("dict['string']: " + (string) dict["string"]); // Debug.Log("dict['float']: " + (double) dict["float"]); // floats come out as doubles // Debug.Log("dict['int']: " + (long) dict["int"]); // ints come out as longs // Debug.Log("dict['unicode']: " + (string) dict["unicode"]); // // var str = Json.Serialize(dict); // // Debug.Log("serialized: " + str); // } // } /// /// This class encodes and decodes JSON strings. /// Spec. details, see http://www.json.org/ /// /// JSON uses Arrays and Objects. These correspond here to the datatypes IList and IDictionary. /// All numbers are parsed to doubles. /// public static class Json { /// /// Parses the string json into a value /// /// A JSON string. /// An List<object>, a Dictionary<string, object>, a double, an integer,a string, null, true, or false public static object Deserialize(string json) { // save the string for debug information if (json == null) { return null; } return Parser.Parse(json); } sealed class Parser : IDisposable { const string WORD_BREAK = "{}[],:\""; public static bool IsWordBreak(char c) { return Char.IsWhiteSpace(c) || WORD_BREAK.IndexOf(c) != -1; } enum TOKEN { NONE, CURLY_OPEN, CURLY_CLOSE, SQUARED_OPEN, SQUARED_CLOSE, COLON, COMMA, STRING, NUMBER, TRUE, FALSE, NULL }; StringReader json; Parser(string jsonString) { json = new StringReader(jsonString); } public static object Parse(string jsonString) { using (var instance = new Parser(jsonString)) { return instance.ParseValue(); } } public void Dispose() { json.Dispose(); json = null; } JsonObject ParseObject() { JsonObject table = new JsonObject(); // ditch opening brace json.Read(); // { while (true) { switch (NextToken) { case TOKEN.NONE: return null; case TOKEN.COMMA: continue; case TOKEN.CURLY_CLOSE: return table; default: // name string name = ParseString(); if (name == null) { return null; } // : if (NextToken != TOKEN.COLON) { return null; } // ditch the colon json.Read(); // value table[name] = ParseValue(); break; } } } List ParseArray() { List array = new List(); // ditch opening bracket json.Read(); // [ var parsing = true; while (parsing) { TOKEN nextToken = NextToken; switch (nextToken) { case TOKEN.NONE: return null; case TOKEN.COMMA: continue; case TOKEN.SQUARED_CLOSE: parsing = false; break; default: object value = ParseByToken(nextToken); array.Add(value); break; } } return array; } object ParseValue() { TOKEN nextToken = NextToken; return ParseByToken(nextToken); } object ParseByToken(TOKEN token) { switch (token) { case TOKEN.STRING: return ParseString(); case TOKEN.NUMBER: return ParseNumber(); case TOKEN.CURLY_OPEN: return ParseObject(); case TOKEN.SQUARED_OPEN: return ParseArray(); case TOKEN.TRUE: return true; case TOKEN.FALSE: return false; case TOKEN.NULL: return null; default: return null; } } string ParseString() { StringBuilder s = new StringBuilder(); char c; // ditch opening quote json.Read(); bool parsing = true; while (parsing) { if (json.Peek() == -1) { parsing = false; break; } c = NextChar; switch (c) { case '"': parsing = false; break; case '\\': if (json.Peek() == -1) { parsing = false; break; } c = NextChar; switch (c) { case '"': case '\\': case '/': s.Append(c); break; case 'b': s.Append('\b'); break; case 'f': s.Append('\f'); break; case 'n': s.Append('\n'); break; case 'r': s.Append('\r'); break; case 't': s.Append('\t'); break; case 'u': var hex = new char[4]; for (int i = 0; i < 4; i++) { hex[i] = NextChar; } s.Append((char)Convert.ToInt32(new string(hex), 16)); break; } break; default: s.Append(c); break; } } return s.ToString(); } object ParseNumber() { string number = NextWord; if (number.IndexOf('.') == -1) { int parsedInt; Int32.TryParse(number, out parsedInt); return parsedInt; } float parsedDouble; float.TryParse(number, out parsedDouble); return parsedDouble; } void EatWhitespace() { while (Char.IsWhiteSpace(PeekChar)) { json.Read(); if (json.Peek() == -1) { break; } } } char PeekChar { get { return Convert.ToChar(json.Peek()); } } char NextChar { get { return Convert.ToChar(json.Read()); } } string NextWord { get { StringBuilder word = new StringBuilder(); while (!IsWordBreak(PeekChar)) { word.Append(NextChar); if (json.Peek() == -1) { break; } } return word.ToString(); } } TOKEN NextToken { get { EatWhitespace(); if (json.Peek() == -1) { return TOKEN.NONE; } switch (PeekChar) { case '{': return TOKEN.CURLY_OPEN; case '}': json.Read(); return TOKEN.CURLY_CLOSE; case '[': return TOKEN.SQUARED_OPEN; case ']': json.Read(); return TOKEN.SQUARED_CLOSE; case ',': json.Read(); return TOKEN.COMMA; case '"': return TOKEN.STRING; case ':': return TOKEN.COLON; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': return TOKEN.NUMBER; } switch (NextWord) { case "false": return TOKEN.FALSE; case "true": return TOKEN.TRUE; case "null": return TOKEN.NULL; } return TOKEN.NONE; } } } /// /// Converts a IDictionary / IList object or a simple type (string, int, etc.) into a JSON string /// /// A Dictionary<string, object> / List<object> /// A JSON encoded string, or null if object 'json' is not serializable public static string Serialize(object obj) { return Serializer.Serialize(obj); } sealed class Serializer { StringBuilder builder; Serializer() { builder = new StringBuilder(); } public static string Serialize(object obj) { var instance = new Serializer(); instance.SerializeValue(obj); return instance.builder.ToString(); } void SerializeValue(object value) { IList asList; IDictionary asDict; string asStr; if (value == null) { builder.Append("null"); } else if ((asStr = value as string) != null) { SerializeString(asStr); } else if (value is bool) { builder.Append((bool)value ? "true" : "false"); } else if ((asList = value as IList) != null) { SerializeArray(asList); } else if ((asDict = value as IDictionary) != null) { SerializeObject(asDict); } else if (value is char) { SerializeString(new string((char)value, 1)); } else { SerializeOther(value); } } void SerializeObject(IDictionary obj) { bool first = true; builder.Append('{'); foreach (object e in obj.Keys) { if (!first) { builder.Append(','); } SerializeString(e.ToString()); builder.Append(':'); SerializeValue(obj[e]); first = false; } builder.Append('}'); } void SerializeArray(IList anArray) { builder.Append('['); bool first = true; foreach (object obj in anArray) { if (!first) { builder.Append(','); } SerializeValue(obj); first = false; } builder.Append(']'); } void SerializeString(string str) { builder.Append('\"'); char[] charArray = str.ToCharArray(); foreach (var c in charArray) { switch (c) { case '"': builder.Append("\\\""); break; case '\\': builder.Append("\\\\"); break; case '\b': builder.Append("\\b"); break; case '\f': builder.Append("\\f"); break; case '\n': builder.Append("\\n"); break; case '\r': builder.Append("\\r"); break; case '\t': builder.Append("\\t"); break; default: int codepoint = Convert.ToInt32(c); if ((codepoint >= 32) && (codepoint <= 126)) { builder.Append(c); } else { builder.Append("\\u"); builder.Append(codepoint.ToString("x4")); } break; } } builder.Append('\"'); } void SerializeOther(object value) { // NOTE: decimals lose precision during serialization. // They always have, I'm just letting you know. // Previously floats and doubles lost precision too. if (value is float) { builder.Append(((float)value).ToString("R")); } else if (value is int || value is uint || value is long || value is sbyte || value is byte || value is short || value is ushort || value is ulong) { builder.Append(value); } else if (value is double || value is decimal) { builder.Append(Convert.ToDouble(value).ToString("R")); } else { SerializeString(value.ToString()); } } } } public class JsonObject : Dictionary { public new object this[string indexKey] { set { base[indexKey] = value; } get { object tmp = default(object); base.TryGetValue(indexKey, out tmp); return tmp; } } } } ================================================ FILE: SGFCore/Codec/PBSerializer.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 封装Protobuf(https://github.com/google/protobuf)以提供简捷的使用方式 * Package Protobuf (https://github.com/google/protobuf) to provide a simple way to use * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using ProtoBuf; using ProtoBuf.Meta; using System.IO; namespace SGF.Codec { /// /// 序列化帮助类 /// public class PBSerializer { public static T Clone(T data) { byte[] buffer = NSerialize(data); return NDeserialize(buffer); } /// /// 序列化pb数据 /// /// /// /// public static byte[] NSerialize(T t) { byte[] buffer = null; using (MemoryStream m = new MemoryStream()) { Serializer.Serialize(m, t); m.Position = 0; int length = (int)m.Length; buffer = new byte[length]; m.Read(buffer, 0, length); } return buffer; } public static byte[] NSerialize(object t) { byte[] buffer = null; using (MemoryStream m = new MemoryStream()) { if (t != null) { RuntimeTypeModel.Default.Serialize(m, t); } m.Position = 0; int length = (int)m.Length; buffer = new byte[length]; m.Read(buffer, 0, length); } return buffer; } public static int NSerialize(object t, byte[] buffer) { using (MemoryStream m = new MemoryStream()) { if (t != null) { RuntimeTypeModel.Default.Serialize(m, t); } m.Position = 0; int length = (int)m.Length; m.Read(buffer, 0, length); return length; } return 0; } /// /// 反序列化pb数据 /// /// /// /// public static T NDeserialize(byte[] buffer) { T t = default(T); using (MemoryStream m = new MemoryStream(buffer)) { t = Serializer.Deserialize(m); } return t; } public static object NDeserialize(byte[] buffer, System.Type type) { object t = null; using (MemoryStream m = new MemoryStream(buffer)) { t = RuntimeTypeModel.Default.Deserialize(m, null, type); } return t; } public static object NDeserialize(MemoryStream buffer, System.Type type) { object t = null; t = RuntimeTypeModel.Default.Deserialize(buffer, null, type); return t; } public static object NDeserialize(byte[] buffer, int len, System.Type type) { object t = null; using (MemoryStream m = new MemoryStream(buffer)) { t = RuntimeTypeModel.Default.Deserialize(m, null, type, len); } return t; } public static T NDeserialize(Stream stream) { T t = default(T); t = Serializer.Deserialize(stream); return t; } } } ================================================ FILE: SGFCore/Codec/SGFEncoding.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 实现一些常用而【简单】的编解码算法, * 对于一些复杂的算法将采用单独的类来实现 * Implement some common and simple codec algorithms,  * For some complex algorithms will use a separate class to achieve. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; namespace SGF.Codec { public class SGFEncoding { public static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; public static String BytesToHex(byte[] bytes, int size = 0) { if (bytes == null || bytes.Length == 0) { return null; } if (size <= 0 || size > bytes.Length) { size = bytes.Length; } char[] buf = new char[2 * size]; for (int i = 0; i < size; i++) { byte b = bytes[i]; buf[2 * i + 1] = digits[b & 0xF]; b = (byte)(b >> 4); buf[2 * i + 0] = digits[b & 0xF]; } return new String(buf); } public static byte[] HexToBytes(String s) { int len = s.Length; byte[] data = new byte[len / 2]; for (int i = 0; i < len; i += 2) { data[i / 2] = (byte)((CharToValue(s[i]) << 4) + (CharToValue(s[i + 1]))); } return data; } public static string Number2BinString(long value, int bitCnt) { return Number2BinString((ulong) value, bitCnt); } public static string Number2BinString(ulong value, int bitCnt) { string str = ""; for (int i = 0; i < bitCnt; i++) { if ((value & (ulong) (1 << i)) != 0) { str = "1" + str; } else { str = "0" + str; } } return str; } private static byte CharToValue(char ch) { if (ch >= '0' && ch <= '9') { return (byte)(ch - '0'); } else if (ch >= 'a' && ch <= 'f') { return (byte)(ch - 'a' + 10); } else if (ch >= 'A' && ch <= 'F') { return (byte)(ch - 'A' + 10); } return 0; } public static int XORCodec(byte[] buffer, int begin, int len, byte[] key) { if (buffer == null || key == null || key.Length == 0) { return -1; } if (begin + len >= buffer.Length) { return -1; } int blockSize = key.Length; int j = 0; for (j = begin; j < begin + len; j++) { buffer[j] = (byte)(buffer[j] ^ key[(j - begin) % blockSize]); } return j; } public static int XORCodec(byte[] inBytes, byte[] outBytes, byte[] keyBytes) { if (inBytes == null || outBytes == null || keyBytes == null || keyBytes.Length == 0) { return -1; } if (outBytes.Length < inBytes.Length) { return -1; } int blockSize = keyBytes.Length; int j = 0; for (j = 0; j < inBytes.Length; j++) { outBytes[j] = (byte)(inBytes[j] ^ keyBytes[j % blockSize]); } return j; } public static ushort CheckSum(byte[] buffer, int size) { ulong sum = 0; int i = 0; while (size > 1) { sum = sum + BitConverter.ToUInt16(buffer, i); size -= 2; i += 2; } if (size > 0) { sum += buffer[i]; } while ((sum >> 16) != 0) { sum = (sum >> 16) + (sum & 0xffff); } return (ushort)(~sum); } } } ================================================ FILE: SGFCore/Event/Signal.cs ================================================ /* * Copyright (C) 2018 Slicol Tang (slicol@qq.com). All rights reserved. * * 一个高性能的事件(信号)系统 * A high performance event (signal) system * * 它的思路与系统自带的Action类似, * 但是在性能与逻辑上比原生的Action更加可控, * 并且能够以日志的方式进行追踪和调试。 * 这在实际应用中非常有用。 * 并且非常高性能和低GC * Its idea is similar to the Action, * but it is more controllable than the original Action in terms of performance and logic, * and can be tracked and debugged in log mode. * This is very useful in practical applications. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using SGF; namespace SGF.SEvent { public class SignalBase { protected int _methodCount; protected Delegate[] _methods; protected bool _needClean = false; public SignalBase(int capacity) { _methods = new Delegate[capacity]; _methodCount = 0; } public SignalBase() { _methods = new Delegate[10]; _methodCount = 0; } protected void AddListener(Delegate del, bool bInsertAtFirst) { if (bInsertAtFirst) { if (_methods[0] == del) { return; } Delegate[] listTemp; if (_methodCount + 1 > _methods.Length) { listTemp = new Delegate[_methods.Length * 2]; } else { listTemp = new Delegate[_methods.Length]; } bool hasExist = false; int j = 0; listTemp[j++] = del; for (int i = 0; i < _methodCount; i++) { if (_methods[i] == del) { hasExist = true; continue; } listTemp[j++] = _methods[i]; } if (!hasExist) { _methodCount++; } _methods = listTemp; } else { for (int i = 0; i < _methodCount; i++) { if (_methods[i] == del) { return; } } if (_methodCount + 1 > _methods.Length) { Delegate[] listTemp; listTemp = new Delegate[_methods.Length * 2]; Array.Copy(_methods, 0, listTemp, 0, _methodCount); _methods = listTemp; } _methods[_methodCount] = del; _methodCount++; } } protected void RemoveListener(Delegate del) { int j = 0; int c = _methodCount; for (int i = 0; i < c; i++) { if (_methods[i] == del) { _needClean = true; _methods[i] = null; break; } } } public void RemoveAllListeners() { for (int i = 0; i < _methodCount; i++) { _methods[i] = null; } _methodCount = 0; } protected void TryClean() { if (_needClean) { _needClean = false; int i = _methodCount; while (i > 0) { i--; if (_methods[i] == null) { _methodCount--; for (int j = i; j < _methodCount; j++) { _methods[i] = _methods[i + 1]; } } } } } public int GetListenerCount() { return _methodCount; } } /// /// 尽管Signal的实现已经具备很高性能 /// 但是肯定比不上直接的函数调用,所以,如果需要最高性能,请用Delegate /// 但是,Signal在内存上比Delegate有较大优势 /// 请综合考虑 /// public class Signal : SignalBase { public static Signal operator +(Signal p1, Action p2) { p1.AddListener(p2, false); return p1; } public static Signal operator -(Signal p1, Action p2) { p1.RemoveListener(p2); return p1; } public void AddListener(Action a, bool bInsertAtFirst = false) { base.AddListener(a, bInsertAtFirst); } public void RemoveListener(Action a) { base.RemoveListener(a); } public void Invoke() { int c = _methodCount; var methods = _methods; for (int i = 0; i < c; i++) { var item = methods[i]; if (item == null) continue; var action = item as Action; action(); } TryClean(); } public void InvokeSafe() { try { int c = _methodCount; var methods = _methods; for (int i = 0; i < c; i++) { var item = methods[i]; if (item == null) continue; var action = item as Action; action(); } TryClean(); } catch (Exception e) { Debuger.LogError(e); } } public Signal(int capacity) : base(capacity) { } public Signal() { } } public class Signal : SignalBase { public static Signal operator +(Signal p1, Action p2) { p1.AddListener(p2, false); return p1; } public static Signal operator -(Signal p1, Action p2) { p1.RemoveListener(p2); return p1; } public void AddListener(Action a, bool bInsertAtFirst = false) { base.AddListener(a, bInsertAtFirst); } public void RemoveListener(Action a) { base.RemoveListener(a); } public void Invoke(T t1) { int c = _methodCount; var methods = _methods; for (int i = 0; i < c; i++) { var item = methods[i]; if (item == null) continue; var action = item as Action; action(t1); } TryClean(); } public void InvokeSafe(T t) { try { int c = _methodCount; var methods = _methods; for (int i = 0; i < c; i++) { var item = methods[i]; if (item == null) continue; var action = item as Action; action(t); } TryClean(); } catch (Exception e) { Debuger.LogError(e); } } public Signal(int capacity) : base(capacity) { } public Signal() { } } public class Signal : SignalBase { public static Signal operator +(Signal p1, Action p2) { p1.AddListener(p2, false); return p1; } public static Signal operator -(Signal p1, Action p2) { p1.RemoveListener(p2); return p1; } public void AddListener(Action a, bool bInsertAtFirst = false) { base.AddListener(a, bInsertAtFirst); } public void RemoveListener(Action a) { base.RemoveListener(a); } public void Invoke(T1 t1, T2 t2) { int c = _methodCount; var methods = _methods; for (int i = 0; i < c; i++) { var item = methods[i]; if (item == null) continue; var action = item as Action; action(t1, t2); } TryClean(); } public void InvokeSafe(T1 t1, T2 t2) { try { int c = _methodCount; var methods = _methods; for (int i = 0; i < c; i++) { var item = methods[i]; if (item == null) continue; var action = item as Action; action(t1, t2); } TryClean(); } catch (Exception e) { Debuger.LogError(e); } } public Signal(int capacity) : base(capacity) { } public Signal() { } } public class Signal : SignalBase { public static Signal operator +(Signal p1, Action p2) { p1.AddListener(p2, false); return p1; } public static Signal operator -(Signal p1, Action p2) { p1.RemoveListener(p2); return p1; } public void AddListener(Action a, bool bInsertAtFirst = false) { base.AddListener(a, bInsertAtFirst); } public void RemoveListener(Action a) { base.RemoveListener(a); } public void Invoke(T1 t1, T2 t2, T3 t3) { int c = _methodCount; var methods = _methods; for (int i = 0; i < c; i++) { var item = methods[i]; if (item == null) continue; var action = item as Action; action(t1, t2, t3); } TryClean(); } public void InvokeSafe(T1 t1, T2 t2, T3 t3) { try { int c = _methodCount; var methods = _methods; for (int i = 0; i < c; i++) { var item = methods[i]; if (item == null) continue; var action = item as Action; action(t1, t2, t3); } TryClean(); } catch (Exception e) { Debuger.LogError(e); } } public Signal(int capacity) : base(capacity) { } public Signal() { } } public class Signal : SignalBase { public static Signal operator +(Signal p1, Action p2) { p1.AddListener(p2, false); return p1; } public static Signal operator -(Signal p1, Action p2) { p1.RemoveListener(p2); return p1; } public void AddListener(Action a, bool bInsertAtFirst = false) { base.AddListener(a, bInsertAtFirst); } public void RemoveListener(Action a) { base.RemoveListener(a); } public void Invoke(T1 t1, T2 t2, T3 t3, T4 t4) { int c = _methodCount; var methods = _methods; for (int i = 0; i < c; i++) { var item = methods[i]; if (item == null) continue; var action = item as Action; action(t1, t2, t3, t4); } TryClean(); } public void InvokeSafe(T1 t1, T2 t2, T3 t3, T4 t4) { try { int c = _methodCount; var methods = _methods; for (int i = 0; i < c; i++) { var item = methods[i]; if (item == null) continue; var action = item as Action; action(t1, t2, t3, t4); } TryClean(); } catch (Exception e) { Debuger.LogError(e); } } public Signal(int capacity) : base(capacity) { } public Signal() { } } } ================================================ FILE: SGFCore/Extension/CollectionExtensions.cs ================================================ using System; using System.Collections; using System.Collections.Generic; using System.Linq; namespace SGF.Extension { public static class CollectionExtensions { private static Random m_Random = new Random(); /** Returns all elements of the source which are of FilterType. */ public static IEnumerable FilterByType(this IEnumerable source) where T : class where TFilter : class, T { return source.Where(item => item as TFilter != null).Cast(); } /// /// ƳԪ /// /// /// /// public static void RemoveAllBut(this List source, Predicate match) { Predicate nomatch = item => !match(item); source.RemoveAll(nomatch); } /// /// ǷΪ /// /// /// /// public static bool IsEmpty(this ICollection collection) { return collection.Count == 0; } /// /// ׷Ԫ /// /// /// /// public static void AddRange(this ICollection collection, IEnumerable other) { if (other == null) //nothing to add { return; } foreach (var obj in other) { collection.Add(obj); } } /// /// лַ /// ʽ{a, b, c} /// /// /// /// public static string ToListString(this IEnumerable source) { if (source == null) { return "null"; } if (source.Count() == 0) { return "[]"; } if (source.Count() == 1) { return "[" + source.First() + "]"; } var s = ""; s += source.ButFirst().Aggregate(s, (res, x) => res + ", " + x.ToListString()); s = "[" + source.First().ToListString() + s + "]"; return s; } /// /// лַ /// /// /// private static string ToListString(this object obj) { if (obj == null) { return ""; } if (obj is string) { return obj.ToString(); } var objAsList = obj as IEnumerable; return objAsList == null ? obj.ToString() : objAsList.Cast().ToListString(); } /** Returns an enumerable of all elements of the given list but the first, keeping them in order. */ public static IEnumerable ButFirst(this IEnumerable source) { return source.Skip(1); } /** Returns an enumarable of all elements in the given list but the last, keeping them in order. */ public static IEnumerable ButLast(this IEnumerable source) { var lastX = default(T); var first = true; foreach (var x in source) { if (first) { first = false; } else { yield return lastX; } lastX = x; } } /// /// ݸķԪ /// /// /// /// /// public static T MaxBy(this IEnumerable source, Func score) { return source.Aggregate((x, y) => score(x).CompareTo(score(y)) > 0 ? x : y); } /** Finds the maximum element in the source as scored by the given function. */ //public static s2 MinBy(this IEnumerable source, Func score) //{ // return source.Aggregate((x, y) => score(x).CompareTo(score(y)) < 0 ? x : y); //} public static TSource MinBy(this IEnumerable source, Func selector) { return source.MinBy(selector, Comparer.Default); } public static TSource MinBy(this IEnumerable source, Func selector, IComparer comparer) { source.ThrowIfNull("source"); selector.ThrowIfNull("selector"); comparer.ThrowIfNull("comparer"); using (IEnumerator sourceIterator = source.GetEnumerator()) { if (!sourceIterator.MoveNext()) { throw new InvalidOperationException("Sequence was empty"); } TSource min = sourceIterator.Current; TKey minKey = selector(min); while (sourceIterator.MoveNext()) { TSource candidate = sourceIterator.Current; TKey candidateProjected = selector(candidate); if (comparer.Compare(candidateProjected, minKey) < 0) { min = candidate; minKey = candidateProjected; } } return min; } } public static TSource MaxBy(this IEnumerable source, Func selector) { return source.MaxBy(selector, Comparer.Default); } public static TSource MaxBy(this IEnumerable source, Func selector, IComparer comparer) { source.ThrowIfNull("source"); selector.ThrowIfNull("selector"); comparer.ThrowIfNull("comparer"); using (IEnumerator sourceIterator = source.GetEnumerator()) { if (!sourceIterator.MoveNext()) { throw new InvalidOperationException("Sequence was empty"); } TSource max = sourceIterator.Current; TKey maxKey = selector(max); while (sourceIterator.MoveNext()) { TSource candidate = sourceIterator.Current; TKey candidateProjected = selector(candidate); if (comparer.Compare(candidateProjected, maxKey) > 0) { max = candidate; maxKey = candidateProjected; } } return max; } } /** Returns a enumerable with elements in order, but the first element is moved to the end. */ //TODO consider changing left to something more universal public static IEnumerable RotateLeft(this IEnumerable source) { var enumeratedList = source as IList ?? source.ToList(); return enumeratedList.ButFirst().Concat(enumeratedList.Take(1)); } /** Returns a enumerable with elements in order, but the last element is moved to the front. */ public static IEnumerable RotateRight(this IEnumerable source) { var enumeratedList = source as IList ?? source.ToList(); yield return enumeratedList.Last(); foreach (var item in enumeratedList.ButLast()) { yield return item; } } /** Returns a random element from the list. */ public static T RandomItem(this IEnumerable source) { return source.SampleRandom(1).First(); } /** Returns a random sample from the list. */ public static IEnumerable SampleRandom(this IEnumerable source, int sampleCount) { if (source == null) { throw new ArgumentNullException("source"); } if (sampleCount < 0) { throw new ArgumentOutOfRangeException("sampleCount"); } /* Reservoir sampling. */ var samples = new List(); //Must be 1, otherwise we have to use Range(0, i + 1) var i = 1; foreach (var item in source) { if (i <= sampleCount) { samples.Add(item); } else { // Randomly replace elements in the reservoir with a decreasing probability. var r = m_Random.Next(0, i); if (r < sampleCount) { samples[r] = item; } } i++; } return samples; } /// /// /// /// /// public static void Shuffle(this IList source) { var n = source.Count; while (n > 1) { n--; var k = m_Random.Next(0, n + 1); var value = source[k]; source[k] = source[n]; source[n] = value; } } public static IEnumerable TakeHalf(this IEnumerable source) { int count = source.Count(); return source.Take(count / 2); } /** Find an element in a collection by binary searching. This requires the collection to be sorted on the values returned by getSubElement This will compare some derived property of the elements in the collection, rather than the elements themselves. */ public static int BinarySearch(this ICollection source, TElement value, Func getSubElement) { return BinarySearch(source, value, getSubElement, 0, source.Count, null); } /** Find an element in a collection by binary searching. This requires the collection to be sorted on the values returned by getSubElement This will compare some derived property of the elements in the collection, rather than the elements themselves. */ public static int BinarySearch(this ICollection source, TElement value, Func getSubElement, IComparer comparer) { return BinarySearch(source, value, getSubElement, 0, source.Count, comparer); } /** Find an element in a collection by binary searching. This requires the collection to be sorted on the values returned by getSubElement This will compare some derived property of the elements in the collection, rather than the elements themselves. */ public static int BinarySearch(this ICollection source, TElement value, Func getSubElement, int index, int length) { return BinarySearch(source, value, getSubElement, index, length, null); } /** Find an element in a collection by binary searching. This requires the collection to be sorted on the values returned by getSubElement This will compare some derived property of the elements in the collection, rather than the elements themselves. */ public static int BinarySearch(this ICollection source, TElement value, Func getSubElement, int index, int length, IComparer comparer) { if (index < 0) { throw new ArgumentOutOfRangeException("index", "index is less than the lower bound of array."); } if (length < 0) { throw new ArgumentOutOfRangeException("length", "Value has to be >= 0."); } // re-ordered to avoid possible integer overflow if (index > source.Count - length) { throw new ArgumentException( "index and length do not specify a valid range in array."); } if (comparer == null) { comparer = Comparer.Default; } int min = index; int max = index + length - 1; int cmp; int mid; while (min <= max) { mid = (min + ((max - min) >> 1)); cmp = comparer.Compare( getSubElement(source.ElementAt(mid)), value); if (cmp == 0) return mid; if (cmp > 0) { max = mid - 1; } else { min = mid + 1; } } return ~min; } public static bool AreSequencesEqual(IEnumerable s1, IEnumerable s2) where T : IComparable { ObjectExtensions.ThrowIfNull(s1, "s1"); ObjectExtensions.ThrowIfNull(s2, "s2"); var list1 = s1.ToList(); var list2 = s2.ToList(); if (list1.Count != list2.Count) return false; for (int i = 0; i < list1.Count; i++) { if (list1[i].CompareTo(list2[i]) != 0) return false; } return true; } public static string SequenceToString(this IEnumerable sequence) { if (sequence == null) return "null"; if (!sequence.Any()) return ""; return sequence.Aggregate((x, y) => x + y); } } } ================================================ FILE: SGFCore/Extension/ObjectExtensions.cs ================================================ using System; using System.Collections; using System.Text; namespace SGF.Extension { public static class ObjectExtensions { /// /// 对象如果为Null,抛出异常 /// /// /// 异常消息 public static void ThrowIfNull(this object o, string message) { if (o == null) throw new NullReferenceException(message); } } } ================================================ FILE: SGFCore/Extension/StreamExtension.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System.IO; namespace SGF.Extension { public static class StreamExtension { public static long CopyTo(this Stream source, Stream destination) { byte[] buffer = new byte[2048]; int bytesRead; long totalBytes = 0; while ((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0) { destination.Write(buffer, 0, bytesRead); totalBytes += bytesRead; } return totalBytes; } } } ================================================ FILE: SGFCore/Extension/StringExtensions.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 提供String的扩展方法 * Provide String extension method * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; namespace SGF.Extension { public static class StringExtensions { public static int ToInt(this string target, int defaultValue = 0) { int.TryParse(target, out defaultValue); return defaultValue; } public static uint ToUInt(this string target, uint defaultValue = 0) { uint.TryParse(target, out defaultValue); return defaultValue; } public static long ToLong(this string target, long defaultValue = 0) { long.TryParse(target, out defaultValue); return defaultValue; } public static ulong ToULong(this string target, ulong defaultValue = 0) { ulong.TryParse(target, out defaultValue); return defaultValue; } public static double ToDouble(this string target, double defaultValue = 0) { double.TryParse(target, out defaultValue); return defaultValue; } public static float ToFloat(this string target, float defaultValue = 0) { float.TryParse(target, out defaultValue); return defaultValue; } } } ================================================ FILE: SGFCore/G3Lite/IndexTypes.cs ================================================ using System; namespace SGF.G3Lite { public struct Index3 : IComparable, IEquatable { public int a; public int b; public int c; public Index3(int z) { a = b = c = z; } public Index3(int ii, int jj, int kk) { a = ii; b = jj; c = kk; } public Index3(int[] i2) { a = i2[0]; b = i2[1]; c = i2[2]; } public Index3(Index3 copy) { a = copy.a; b = copy.b; c = copy.b; } // reverse last two indices if cycle is true (useful for cw/ccw codes) public Index3(int ii, int jj, int kk, bool cycle) { a = ii; if (cycle) { b = kk; c = jj; } else { b = jj; c = kk; } } static public readonly Index3 Zero = new Index3(0, 0, 0); static public readonly Index3 One = new Index3(1, 1, 1); static public readonly Index3 Max = new Index3(int.MaxValue, int.MaxValue, int.MaxValue); static public readonly Index3 Min = new Index3(int.MinValue, int.MinValue, int.MinValue); public int this[int key] { get { return (key == 0) ? a : (key == 1) ? b : c; } set { if (key == 0) a = value; else if (key == 1) b = value; else c = value; } } public int[] array { get { return new int[] { a, b, c }; } } public int LengthSquared { get { return a * a + b * b + c * c; } } public int Length { get { return (int)Math.Sqrt(LengthSquared); } } public void Set(Index3 o) { a = o[0]; b = o[1]; c = o[2]; } public void Set(int ii, int jj, int kk) { a = ii; b = jj; c = kk; } public static Index3 operator -(Index3 v) { return new Index3(-v.a, -v.b, -v.c); } public static Index3 operator *(int f, Index3 v) { return new Index3(f * v.a, f * v.b, f * v.c); } public static Index3 operator *(Index3 v, int f) { return new Index3(f * v.a, f * v.b, f * v.c); } public static Index3 operator /(Index3 v, int f) { return new Index3(v.a / f, v.b / f, v.c / f); } public static Index3 operator *(Index3 a, Index3 b) { return new Index3(a.a * b.a, a.b * b.b, a.c * b.c); } public static Index3 operator /(Index3 a, Index3 b) { return new Index3(a.a / b.a, a.b / b.b, a.c / b.c); } public static Index3 operator +(Index3 v0, Index3 v1) { return new Index3(v0.a + v1.a, v0.b + v1.b, v0.c + v1.c); } public static Index3 operator +(Index3 v0, int f) { return new Index3(v0.a + f, v0.b + f, v0.c + f); } public static Index3 operator -(Index3 v0, Index3 v1) { return new Index3(v0.a - v1.a, v0.b - v1.b, v0.c - v1.c); } public static Index3 operator -(Index3 v0, int f) { return new Index3(v0.a - f, v0.b - f, v0.c - f); } public static bool operator ==(Index3 a, Index3 b) { return (a.a == b.a && a.b == b.b && a.c == b.c); } public static bool operator !=(Index3 a, Index3 b) { return (a.a != b.a || a.b != b.b || a.c != b.c); } public override bool Equals(object obj) { return this == (Index3)obj; } public override int GetHashCode() { unchecked // Overflow is fine, just wrap { int hash = (int)2166136261; // Suitable nullity checks etc, of course :) hash = (hash * 16777619) ^ a.GetHashCode(); hash = (hash * 16777619) ^ b.GetHashCode(); hash = (hash * 16777619) ^ c.GetHashCode(); return hash; } } public int CompareTo(Index3 other) { if (a != other.a) return a < other.a ? -1 : 1; else if (b != other.b) return b < other.b ? -1 : 1; else if (c != other.c) return c < other.c ? -1 : 1; return 0; } public bool Equals(Index3 other) { return (a == other.a && b == other.b && c == other.c); } public override string ToString() { return string.Format("[{0},{1},{2}]", a, b, c); } } public struct Index2 : IComparable, IEquatable { public int a; public int b; public Index2(int z) { a = b = z; } public Index2(int ii, int jj) { a = ii; b = jj; } public Index2(int[] i2) { a = i2[0]; b = i2[1]; } public Index2(Index2 copy) { a = copy.a; b = copy.b; } static public readonly Index2 Zero = new Index2(0, 0); static public readonly Index2 One = new Index2(1, 1); static public readonly Index2 Max = new Index2(int.MaxValue, int.MaxValue); static public readonly Index2 Min = new Index2(int.MinValue, int.MinValue); public int this[int key] { get { return (key == 0) ? a : b; } set { if (key == 0) a = value; else b = value; } } public int[] array { get { return new int[] { a, b }; } } public int LengthSquared { get { return a * a + b * b; } } public int Length { get { return (int)Math.Sqrt(LengthSquared); } } public void Set(Index2 o) { a = o[0]; b = o[1]; } public void Set(int ii, int jj) { a = ii; b = jj; } public static Index2 operator -(Index2 v) { return new Index2(-v.a, -v.b); } public static Index2 operator *(int f, Index2 v) { return new Index2(f * v.a, f * v.b); } public static Index2 operator *(Index2 v, int f) { return new Index2(f * v.a, f * v.b); } public static Index2 operator /(Index2 v, int f) { return new Index2(v.a / f, v.b / f); } public static Index2 operator *(Index2 a, Index2 b) { return new Index2(a.a * b.a, a.b * b.b); } public static Index2 operator /(Index2 a, Index2 b) { return new Index2(a.a / b.a, a.b / b.b); } public static Index2 operator +(Index2 v0, Index2 v1) { return new Index2(v0.a + v1.a, v0.b + v1.b); } public static Index2 operator +(Index2 v0, int f) { return new Index2(v0.a + f, v0.b + f); } public static Index2 operator -(Index2 v0, Index2 v1) { return new Index2(v0.a - v1.a, v0.b - v1.b); } public static Index2 operator -(Index2 v0, int f) { return new Index2(v0.a - f, v0.b - f); } public static bool operator ==(Index2 a, Index2 b) { return (a.a == b.a && a.b == b.b); } public static bool operator !=(Index2 a, Index2 b) { return (a.a != b.a || a.b != b.b); } public override bool Equals(object obj) { return this == (Index2)obj; } public override int GetHashCode() { unchecked // Overflow is fine, just wrap { int hash = (int)2166136261; // Suitable nullity checks etc, of course :) hash = (hash * 16777619) ^ a.GetHashCode(); hash = (hash * 16777619) ^ b.GetHashCode(); return hash; } } public int CompareTo(Index2 other) { if (a != other.a) return a < other.a ? -1 : 1; else if (b != other.b) return b < other.b ? -1 : 1; return 0; } public bool Equals(Index2 other) { return (a == other.a && b == other.b); } public override string ToString() { return string.Format("[{0},{1}]", a, b); } } public struct Index4 { public int a; public int b; public int c; public int d; public Index4(int z) { a = b = c = d = z; } public Index4(int aa, int bb, int cc, int dd) { a = aa; b = bb; c = cc; d = dd; } public Index4(int[] i2) { a = i2[0]; b = i2[1]; c = i2[2]; d = i2[3]; } public Index4(Index4 copy) { a = copy.a; b = copy.b; c = copy.b; d = copy.d; } static public readonly Index4 Zero = new Index4(0, 0, 0, 0); static public readonly Index4 One = new Index4(1, 1, 1, 1); static public readonly Index4 Max = new Index4(int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue); public int this[int key] { get { return (key == 0) ? a : (key == 1) ? b : (key == 2) ? c : d; } set { if (key == 0) a = value; else if (key == 1) b = value; else if (key == 2) c = value; else d = value; } } public int[] array { get { return new int[4] { a, b, c, d }; } } public int LengthSquared { get { return a * a + b * b + c * c + d * d; } } public int Length { get { return (int)Math.Sqrt(LengthSquared); } } public void Set(Index4 o) { a = o[0]; b = o[1]; c = o[2]; d = o[3]; } public void Set(int aa, int bb, int cc, int dd) { a = aa; b = bb; c = cc; d = dd; } public bool Contains(int val) { return a == val || b == val || c == val || d == val; } public void Sort() { int tmp; // if we use 2 temp ints, we can swap in a different order where some test pairs // could be done simultaneously, but no idea if compiler would optimize that anyway... if (d < c) { tmp = d; d = c; c = tmp; } if (c < b) { tmp = c; c = b; b = tmp; } if (b < a) { tmp = b; b = a; a = tmp; } // now a is smallest value if (b > c) { tmp = c; c = b; b = tmp; } if (c > d) { tmp = d; d = c; c = tmp; } // now d is largest value if (b > c) { tmp = c; c = b; b = tmp; } // bow b,c are sorted } public static Index4 operator -(Index4 v) { return new Index4(-v.a, -v.b, -v.c, -v.d); } public static Index4 operator *(int f, Index4 v) { return new Index4(f * v.a, f * v.b, f * v.c, f * v.d); } public static Index4 operator *(Index4 v, int f) { return new Index4(f * v.a, f * v.b, f * v.c, f * v.d); } public static Index4 operator /(Index4 v, int f) { return new Index4(v.a / f, v.b / f, v.c / f, v.d / f); } public static Index4 operator *(Index4 a, Index4 b) { return new Index4(a.a * b.a, a.b * b.b, a.c * b.c, a.d * b.d); } public static Index4 operator /(Index4 a, Index4 b) { return new Index4(a.a / b.a, a.b / b.b, a.c / b.c, a.d / b.d); } public static Index4 operator +(Index4 v0, Index4 v1) { return new Index4(v0.a + v1.a, v0.b + v1.b, v0.c + v1.c, v0.d + v1.d); } public static Index4 operator +(Index4 v0, int f) { return new Index4(v0.a + f, v0.b + f, v0.c + f, v0.d + f); } public static Index4 operator -(Index4 v0, Index4 v1) { return new Index4(v0.a - v1.a, v0.b - v1.b, v0.c - v1.c, v0.d - v1.d); } public static Index4 operator -(Index4 v0, int f) { return new Index4(v0.a - f, v0.b - f, v0.c - f, v0.d - f); } public static bool operator ==(Index4 a, Index4 b) { return (a.a == b.a && a.b == b.b && a.c == b.c && a.d == b.d); } public static bool operator !=(Index4 a, Index4 b) { return (a.a != b.a || a.b != b.b || a.c != b.c || a.d != b.d); } public override bool Equals(object obj) { return this == (Index4)obj; } public override int GetHashCode() { unchecked // Overflow is fine, just wrap { int hash = (int)2166136261; // Suitable nullity checks etc, of course :) hash = (hash * 16777619) ^ a.GetHashCode(); hash = (hash * 16777619) ^ b.GetHashCode(); hash = (hash * 16777619) ^ c.GetHashCode(); hash = (hash * 16777619) ^ d.GetHashCode(); return hash; } } public int CompareTo(Index4 other) { if (a != other.a) return a < other.a ? -1 : 1; else if (b != other.b) return b < other.b ? -1 : 1; else if (c != other.c) return c < other.c ? -1 : 1; else if (d != other.d) return d < other.d ? -1 : 1; return 0; } public bool Equals(Index4 other) { return (a == other.a && b == other.b && c == other.c && d == other.d); } public override string ToString() { return string.Format("[{0},{1},{2},{3}]", a, b, c, d); } } } ================================================ FILE: SGFCore/G3Lite/MathUtil.cs ================================================ using System; using System.Collections.Generic; namespace SGF.G3Lite { public static class MathUtil { public const double Deg2Rad = (Math.PI / 180.0); public const double Rad2Deg = (180.0 / Math.PI); public const double TwoPI = 2.0 * Math.PI; public const double FourPI = 4.0 * Math.PI; public const double HalfPI = 0.5 * Math.PI; public const double ZeroTolerance = 1e-08; public const double Epsilon = 2.2204460492503131e-016; public const double SqrtTwo = 1.41421356237309504880168872420969807; public const double SqrtTwoInv = 1.0 / SqrtTwo; public const double SqrtThree = 1.73205080756887729352744634150587236; public const float Deg2Radf = (float)(Math.PI / 180.0); public const float Rad2Degf = (float)(180.0 / Math.PI); public const float PIf = (float)(Math.PI); public const float TwoPIf = 2.0f * PIf; public const float HalfPIf = 0.5f * PIf; public const float SqrtTwof = 1.41421356237f; public const float ZeroTolerancef = 1e-06f; public const float Epsilonf = 1.192092896e-07F; public static bool IsFinite(double d) { return double.IsInfinity(d) == false && double.IsNaN(d) == false; } public static bool IsFinite(float d) { return float.IsInfinity(d) == false && float.IsNaN(d) == false; } public static bool EpsilonEqual(double a, double b, double epsilon = MathUtil.Epsilon) { return Math.Abs(a - b) <= epsilon; } public static bool EpsilonEqual(float a, float b, float epsilon = MathUtil.Epsilonf) { return (float)Math.Abs(a - b) <= epsilon; } // ugh C# generics so limiting... public static T Clamp(T f, T low, T high) where T : IComparable { if (f.CompareTo(low) < 0) return low; else if (f.CompareTo(high) > 0) return high; else return f; } public static float Clamp(float f, float low, float high) { return (f < low) ? low : (f > high) ? high : f; } public static double Clamp(double f, double low, double high) { return (f < low) ? low : (f > high) ? high : f; } public static int Clamp(int f, int low, int high) { return (f < low) ? low : (f > high) ? high : f; } public static int ModuloClamp(int f, int N) { while (f < 0) f += N; return f % N; } // fMinMaxValue may be signed public static float RangeClamp(float fValue, float fMinMaxValue) { return Clamp(fValue, -Math.Abs(fMinMaxValue), Math.Abs(fMinMaxValue)); } public static double RangeClamp(double fValue, double fMinMaxValue) { return Clamp(fValue, -Math.Abs(fMinMaxValue), Math.Abs(fMinMaxValue)); } public static float SignedClamp(float f, float fMax) { return Clamp(Math.Abs(f), 0, fMax) * Math.Sign(f); } public static double SignedClamp(double f, double fMax) { return Clamp(Math.Abs(f), 0, fMax) * Math.Sign(f); } public static float SignedClamp(float f, float fMin, float fMax) { return Clamp(Math.Abs(f), fMin, fMax) * Math.Sign(f); } public static double SignedClamp(double f, double fMin, double fMax) { return Clamp(Math.Abs(f), fMin, fMax) * Math.Sign(f); } public static bool InRange(float f, float low, float high) { return f >= low && f <= high; } public static bool InRange(double f, double low, double high) { return f >= low && f <= high; } public static bool InRange(int f, int low, int high) { return f >= low && f <= high; } // clamps theta to angle interval [min,max]. should work for any theta, // regardless of cycles, however min & max values should be in range // [-360,360] and min < max public static double ClampAngleDeg(double theta, double min, double max) { // convert interval to center/extent - [c-e,c+e] double c = (min + max) * 0.5; double e = max - c; // get rid of extra rotations theta = theta % 360; // shift to origin, then convert theta to +- 180 theta -= c; if (theta < -180) theta += 360; else if (theta > 180) theta -= 360; // clamp to extent if (theta < -e) theta = -e; else if (theta > e) theta = e; // shift back return theta + c; } // clamps theta to angle interval [min,max]. should work for any theta, // regardless of cycles, however min & max values should be in range // [-2_PI,2_PI] and min < max public static double ClampAngleRad(double theta, double min, double max) { // convert interval to center/extent - [c-e,c+e] double c = (min + max) * 0.5; double e = max - c; // get rid of extra rotations theta = theta % TwoPI; // shift to origin, then convert theta to +- 180 theta -= c; if (theta < -Math.PI) theta += TwoPI; else if (theta > Math.PI) theta -= TwoPI; // clamp to extent if (theta < -e) theta = -e; else if (theta > e) theta = e; // shift back return theta + c; } // for ((i++) % N)-type loops, but where we might be using (i--) public static int WrapSignedIndex(int val, int mod) { while (val < 0) val += mod; return val % mod; } // compute min and max of a,b,c with max 3 comparisons (sometimes 2) public static void MinMax(double a, double b, double c, out double min, out double max) { if (a < b) { if (a < c) { min = a; max = Math.Max(b, c); } else { min = c; max = b; } } else { if (a > c) { max = a; min = Math.Min(b, c); } else { min = b; max = c; } } } public static double Min(double a, double b, double c) { return Math.Min(a, Math.Min(b, c)); } public static float Min(float a, float b, float c) { return Math.Min(a, Math.Min(b, c)); } public static int Min(int a, int b, int c) { return Math.Min(a, Math.Min(b, c)); } public static double Max(double a, double b, double c) { return Math.Max(a, Math.Max(b, c)); } public static float Max(float a, float b, float c) { return Math.Max(a, Math.Max(b, c)); } public static int Max(int a, int b, int c) { return Math.Max(a, Math.Max(b, c)); } // there are fast approximations to this... public static double InvSqrt(double f) { return f / Math.Sqrt(f); } // normal Atan2 returns in range [-pi,pi], this shifts to [0,2pi] public static double Atan2Positive(double y, double x) { double theta = Math.Atan2(y, x); if (theta < 0) theta = (2 * Math.PI) + theta; return theta; } public static float PlaneAngleD(Vector3 a, Vector3 b, int nPlaneNormalIdx = 1) { a[nPlaneNormalIdx] = b[nPlaneNormalIdx] = 0.0f; a.Normalize(); b.Normalize(); return Vector3.AngleD(a, b); } public static float PlaneAngleSignedD(Vector3 vFrom, Vector3 vTo, int nPlaneNormalIdx = 1) { vFrom[nPlaneNormalIdx] = vTo[nPlaneNormalIdx] = 0.0f; vFrom.Normalize(); vTo.Normalize(); Vector3 c = vFrom.Cross(vTo); if (c.sqrMagnitude < MathUtil.ZeroTolerancef) { // vectors are parallel return vFrom.Dot(vTo) < 0 ? 180.0f : 0; } float fSign = Math.Sign(c[nPlaneNormalIdx]); float fAngle = fSign * Vector3.AngleD(vFrom, vTo); return fAngle; } public static float PlaneAngleSignedD(Vector3 vFrom, Vector3 vTo, Vector3 planeN) { vFrom = vFrom - Vector3.Dot(vFrom, planeN) * planeN; vTo = vTo - Vector3.Dot(vTo, planeN) * planeN; vFrom.Normalize(); vTo.Normalize(); Vector3 c = Vector3.Cross(vFrom, vTo); if (c.sqrMagnitude < MathUtil.ZeroTolerancef) { // vectors are parallel return vFrom.Dot(vTo) < 0 ? 180.0f : 0; } float fSign = Math.Sign(Vector3.Dot(c, planeN)); float fAngle = fSign * Vector3.AngleD(vFrom, vTo); return fAngle; } public static float PlaneAngleSignedD(Vector2 vFrom, Vector2 vTo) { vFrom.Normalize(); vTo.Normalize(); float fSign = Math.Sign(vFrom.Cross(vTo)); float fAngle = fSign * Vector2.AngleD(vFrom, vTo); return fAngle; } public static float Lerp(float a, float b, float t) { return (1.0f - t) * a + (t) * b; } public static double Lerp(double a, double b, double t) { return (1.0 - t) * a + (t) * b; } public static float SmoothStep(float a, float b, float t) { t = t * t * (3.0f - 2.0f * t); return (1.0f - t) * a + (t) * b; } public static double SmoothStep(double a, double b, double t) { t = t * t * (3.0 - 2.0 * t); return (1.0 - t) * a + (t) * b; } public static float SmoothInterp(float a, float b, float t) { float tt = WyvillRise01(t); return (1.0f - tt) * a + (tt) * b; } public static double SmoothInterp(double a, double b, double t) { double tt = WyvillRise01(t); return (1.0 - tt) * a + (tt) * b; } //! if yshift is 0, function approaches y=1 at xZero from y=0. //! speed (> 0) controls how fast it gets there //! yshift pushes the whole graph upwards (so that it actually crosses y=1 at some point) public static float SmoothRise0To1(float fX, float yshift, float xZero, float speed) { double denom = Math.Pow((fX - (xZero - 1)), speed); float fY = (float)((1 + yshift) + (1 / -denom)); return Clamp(fY, 0, 1); } public static float WyvillRise01(float fX) { float d = MathUtil.Clamp(1.0f - fX * fX, 0.0f, 1.0f); return 1 - (d * d * d); } public static double WyvillRise01(double fX) { double d = MathUtil.Clamp(1.0 - fX * fX, 0.0, 1.0); return 1 - (d * d * d); } public static float WyvillFalloff01(float fX) { float d = 1 - fX * fX; return (d >= 0) ? (d * d * d) : 0; } public static double WyvillFalloff01(double fX) { double d = 1 - fX * fX; return (d >= 0) ? (d * d * d) : 0; } public static float WyvillFalloff(float fD, float fInnerRad, float fOuterRad) { if (fD > fOuterRad) { return 0; } else if (fD > fInnerRad) { fD -= fInnerRad; fD /= (fOuterRad - fInnerRad); fD = Math.Max(0, Math.Min(1, fD)); float fVal = (1.0f - fD * fD); return fVal * fVal * fVal; } else return 1.0f; } public static double WyvillFalloff(double fD, double fInnerRad, double fOuterRad) { if (fD > fOuterRad) { return 0; } else if (fD > fInnerRad) { fD -= fInnerRad; fD /= (fOuterRad - fInnerRad); fD = Math.Max(0, Math.Min(1, fD)); double fVal = (1.0f - fD * fD); return fVal * fVal * fVal; } else return 1.0; } // lerps from [0,1] for x in range [deadzone,R] public static float LinearRampT(float R, float deadzoneR, float x) { float sign = Math.Sign(x); x = Math.Abs(x); if (x < deadzoneR) return 0.0f; else if (x > R) return sign * 1.0f; else { x = Math.Min(x, R); float d = (x - deadzoneR) / (R - deadzoneR); return sign * d; } } public static bool SolveQuadratic(double a, double b, double c, out double minT, out double maxT) { minT = maxT = 0; if (a == 0 && b == 0) // function is constant... return true; double discrim = b * b - 4.0 * a * c; if (discrim < 0) return false; // no solution // a bit odd but numerically better (says NRIC) double t = -0.5 * (b + Math.Sign(b) * Math.Sqrt(discrim)); minT = t / a; maxT = c / t; if (minT > maxT) { a = minT; minT = maxT; maxT = a; // swap } return true; } static readonly int[] powers_of_10 = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; public static int PowerOf10(int n) { return powers_of_10[n]; } /// /// Iterate from 0 to (nMax-1) using prime-modulo, so we see every index once, but not in-order /// public static IEnumerable ModuloIteration(int nMaxExclusive, int nPrime = 31337) { int i = 0; bool done = false; while (done == false) { yield return i; i = (i + nPrime) % nMaxExclusive; done = (i == 0); } } } } ================================================ FILE: SGFCore/G3Lite/Matrix3.cs ================================================ using System; namespace SGF.G3Lite { public struct Matrix3 { public Vector3 Row0; public Vector3 Row1; public Vector3 Row2; public Matrix3(bool bIdentity) { if (bIdentity) { Row0 = Vector3.AxisX; Row1 = Vector3.AxisY; Row2 = Vector3.AxisZ; } else { Row0 = Row1 = Row2 = Vector3.zero; } } // assumes input is row-major... public Matrix3(float[,] mat) { Row0 = new Vector3(mat[0, 0], mat[0, 1], mat[0, 2]); Row1 = new Vector3(mat[1, 0], mat[1, 1], mat[1, 2]); Row2 = new Vector3(mat[2, 0], mat[2, 1], mat[2, 2]); } public Matrix3(float[] mat) { Row0 = new Vector3(mat[0], mat[1], mat[2]); Row1 = new Vector3(mat[3], mat[4], mat[5]); Row2 = new Vector3(mat[6], mat[7], mat[8]); } public Matrix3(double[,] mat) { Row0 = new Vector3(mat[0, 0], mat[0, 1], mat[0, 2]); Row1 = new Vector3(mat[1, 0], mat[1, 1], mat[1, 2]); Row2 = new Vector3(mat[2, 0], mat[2, 1], mat[2, 2]); } public Matrix3(double[] mat) { Row0 = new Vector3(mat[0], mat[1], mat[2]); Row1 = new Vector3(mat[3], mat[4], mat[5]); Row2 = new Vector3(mat[6], mat[7], mat[8]); } public Matrix3(Func matBufferF) { Row0 = new Vector3(matBufferF(0), matBufferF(1), matBufferF(2)); Row1 = new Vector3(matBufferF(3), matBufferF(4), matBufferF(5)); Row2 = new Vector3(matBufferF(6), matBufferF(7), matBufferF(8)); } public Matrix3(Func matF) { Row0 = new Vector3(matF(0, 0), matF(0, 1), matF(0, 2)); Row1 = new Vector3(matF(1, 0), matF(1, 1), matF(1, 2)); Row2 = new Vector3(matF(2, 0), matF(1, 2), matF(2, 2)); } public Matrix3(float m00, float m11, float m22) { Row0 = new Vector3(m00, 0, 0); Row1 = new Vector3(0, m11, 0); Row2 = new Vector3(0, 0, m22); } public Matrix3(Vector3 v1, Vector3 v2, Vector3 v3, bool bRows) { if (bRows) { Row0 = v1; Row1 = v2; Row2 = v3; } else { Row0 = new Vector3(v1.x, v2.x, v3.x); Row1 = new Vector3(v1.y, v2.y, v3.y); Row2 = new Vector3(v1.z, v2.z, v3.z); } } public Matrix3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22) { Row0 = new Vector3(m00, m01, m02); Row1 = new Vector3(m10, m11, m12); Row2 = new Vector3(m20, m21, m22); } public static readonly Matrix3 Identity = new Matrix3(true); public static readonly Matrix3 Zero = new Matrix3(false); public float this[int r, int c] { get { return (r == 0) ? Row0[c] : ((r == 1) ? Row1[c] : Row2[c]); } set { if (r == 0) Row0[c] = value; else if (r == 1) Row1[c] = value; else Row2[c] = value; } } public float this[int i] { get { return (i > 5) ? Row2[i % 3] : ((i > 2) ? Row1[i % 3] : Row0[i % 3]); } set { if (i > 5) Row2[i % 3] = value; else if (i > 2) Row1[i % 3] = value; else Row0[i % 3] = value; } } public Vector3 Row(int i) { return (i == 0) ? Row0 : (i == 1) ? Row1 : Row2; } public Vector3 Column(int i) { if (i == 0) return new Vector3(Row0.x, Row1.x, Row2.x); else if (i == 1) return new Vector3(Row0.y, Row1.y, Row2.y); else return new Vector3(Row0.z, Row1.z, Row2.z); } public float[] ToBuffer() { return new float[9] { Row0.x, Row0.y, Row0.z, Row1.x, Row1.y, Row1.z, Row2.x, Row2.y, Row2.z }; } public void ToBuffer(float[] buf) { buf[0] = Row0.x; buf[1] = Row0.y; buf[2] = Row0.z; buf[3] = Row1.x; buf[4] = Row1.y; buf[5] = Row1.z; buf[6] = Row2.x; buf[7] = Row2.y; buf[8] = Row2.z; } public static Matrix3 operator *(Matrix3 mat, float f) { return new Matrix3( mat.Row0.x * f, mat.Row0.y * f, mat.Row0.z * f, mat.Row1.x * f, mat.Row1.y * f, mat.Row1.z * f, mat.Row2.x * f, mat.Row2.y * f, mat.Row2.z * f); } public static Matrix3 operator *(float f, Matrix3 mat) { return new Matrix3( mat.Row0.x * f, mat.Row0.y * f, mat.Row0.z * f, mat.Row1.x * f, mat.Row1.y * f, mat.Row1.z * f, mat.Row2.x * f, mat.Row2.y * f, mat.Row2.z * f); } public static Vector3 operator *(Matrix3 mat, Vector3 v) { return new Vector3( mat.Row0.x * v.x + mat.Row0.y * v.y + mat.Row0.z * v.z, mat.Row1.x * v.x + mat.Row1.y * v.y + mat.Row1.z * v.z, mat.Row2.x * v.x + mat.Row2.y * v.y + mat.Row2.z * v.z); } public Vector3 Multiply(ref Vector3 v) { return new Vector3( Row0.x * v.x + Row0.y * v.y + Row0.z * v.z, Row1.x * v.x + Row1.y * v.y + Row1.z * v.z, Row2.x * v.x + Row2.y * v.y + Row2.z * v.z); } public void Multiply(ref Vector3 v, ref Vector3 vOut) { vOut.x = Row0.x * v.x + Row0.y * v.y + Row0.z * v.z; vOut.y = Row1.x * v.x + Row1.y * v.y + Row1.z * v.z; vOut.z = Row2.x * v.x + Row2.y * v.y + Row2.z * v.z; } public static Matrix3 operator *(Matrix3 mat1, Matrix3 mat2) { float m00 = mat1.Row0.x * mat2.Row0.x + mat1.Row0.y * mat2.Row1.x + mat1.Row0.z * mat2.Row2.x; float m01 = mat1.Row0.x * mat2.Row0.y + mat1.Row0.y * mat2.Row1.y + mat1.Row0.z * mat2.Row2.y; float m02 = mat1.Row0.x * mat2.Row0.z + mat1.Row0.y * mat2.Row1.z + mat1.Row0.z * mat2.Row2.z; float m10 = mat1.Row1.x * mat2.Row0.x + mat1.Row1.y * mat2.Row1.x + mat1.Row1.z * mat2.Row2.x; float m11 = mat1.Row1.x * mat2.Row0.y + mat1.Row1.y * mat2.Row1.y + mat1.Row1.z * mat2.Row2.y; float m12 = mat1.Row1.x * mat2.Row0.z + mat1.Row1.y * mat2.Row1.z + mat1.Row1.z * mat2.Row2.z; float m20 = mat1.Row2.x * mat2.Row0.x + mat1.Row2.y * mat2.Row1.x + mat1.Row2.z * mat2.Row2.x; float m21 = mat1.Row2.x * mat2.Row0.y + mat1.Row2.y * mat2.Row1.y + mat1.Row2.z * mat2.Row2.y; float m22 = mat1.Row2.x * mat2.Row0.z + mat1.Row2.y * mat2.Row1.z + mat1.Row2.z * mat2.Row2.z; return new Matrix3(m00, m01, m02, m10, m11, m12, m20, m21, m22); } public static Matrix3 operator +(Matrix3 mat1, Matrix3 mat2) { return new Matrix3(mat1.Row0 + mat2.Row0, mat1.Row1 + mat2.Row1, mat1.Row2 + mat2.Row2, true); } public static Matrix3 operator -(Matrix3 mat1, Matrix3 mat2) { return new Matrix3(mat1.Row0 - mat2.Row0, mat1.Row1 - mat2.Row1, mat1.Row2 - mat2.Row2, true); } public float Determinant { get { float a11 = Row0.x, a12 = Row0.y, a13 = Row0.z, a21 = Row1.x, a22 = Row1.y, a23 = Row1.z, a31 = Row2.x, a32 = Row2.y, a33 = Row2.z; float i00 = a33 * a22 - a32 * a23; float i01 = -(a33 * a12 - a32 * a13); float i02 = a23 * a12 - a22 * a13; return a11 * i00 + a21 * i01 + a31 * i02; } } public Matrix3 Inverse() { float a11 = Row0.x, a12 = Row0.y, a13 = Row0.z, a21 = Row1.x, a22 = Row1.y, a23 = Row1.z, a31 = Row2.x, a32 = Row2.y, a33 = Row2.z; float i00 = a33 * a22 - a32 * a23; float i01 = -(a33 * a12 - a32 * a13); float i02 = a23 * a12 - a22 * a13; float i10 = -(a33 * a21 - a31 * a23); float i11 = a33 * a11 - a31 * a13; float i12 = -(a23 * a11 - a21 * a13); float i20 = a32 * a21 - a31 * a22; float i21 = -(a32 * a11 - a31 * a12); float i22 = a22 * a11 - a21 * a12; float det = a11 * i00 + a21 * i01 + a31 * i02; if (Math.Abs(det) < float.Epsilon) throw new Exception("Matrix3.Inverse: matrix is not invertible"); det = 1.0f / det; return new Matrix3(i00 * det, i01 * det, i02 * det, i10 * det, i11 * det, i12 * det, i20 * det, i21 * det, i22 * det); } public Matrix3 Transpose() { return new Matrix3( Row0.x, Row1.x, Row2.x, Row0.y, Row1.y, Row2.y, Row0.z, Row1.z, Row2.z); } public Quaternion ToQuaternion() { return new Quaternion(this); } public bool EpsilonEqual(Matrix3 m2, float epsilon) { return Row0.EpsilonEqual(m2.Row0, epsilon) && Row1.EpsilonEqual(m2.Row1, epsilon) && Row2.EpsilonEqual(m2.Row2, epsilon); } public static Matrix3 AxisAngleD(Vector3 axis, float angleDeg) { double angle = angleDeg * MathUtil.Deg2Rad; float cs = (float)Math.Cos(angle); float sn = (float)Math.Sin(angle); float oneMinusCos = 1.0f - cs; float x2 = axis[0] * axis[0]; float y2 = axis[1] * axis[1]; float z2 = axis[2] * axis[2]; float xym = axis[0] * axis[1] * oneMinusCos; float xzm = axis[0] * axis[2] * oneMinusCos; float yzm = axis[1] * axis[2] * oneMinusCos; float xSin = axis[0] * sn; float ySin = axis[1] * sn; float zSin = axis[2] * sn; return new Matrix3( x2 * oneMinusCos + cs, xym - zSin, xzm + ySin, xym + zSin, y2 * oneMinusCos + cs, yzm - xSin, xzm - ySin, yzm + xSin, z2 * oneMinusCos + cs); } public override string ToString() { return string.Format("[{0}] [{1}] [{2}]", Row0, Row1, Row2); } public string ToString(string fmt) { return string.Format("[{0}] [{1}] [{2}]", Row0.ToString(fmt), Row1.ToString(fmt), Row2.ToString(fmt)); } } } ================================================ FILE: SGFCore/G3Lite/Quaternion.cs ================================================ using System; namespace SGF.G3Lite { // mostly ported from WildMagic5 Wm5Quaternion, from geometrictools.com public struct Quaternion : IComparable, IEquatable { // note: in Wm5 version, this is a 4-element array stored in order (w,x,y,z). public float x, y, z, w; public Quaternion(float x, float y, float z, float w) { this.x = x; this.y = y; this.z = z; this.w = w; } public Quaternion(float[] v2) { x = v2[0]; y = v2[1]; z = v2[2]; w = v2[3]; } public Quaternion(Quaternion q2) { x = q2.x; y = q2.y; z = q2.z; w = q2.w; } public Quaternion(Vector3 axis, float AngleDeg) { x = y = z = 0; w = 1; SetAxisAngleD(axis, AngleDeg); } public Quaternion(Vector3 vFrom, Vector3 vTo) { x = y = z = 0; w = 1; SetFromTo(vFrom, vTo); } public Quaternion(Quaternion p, Quaternion q, float t) { x = y = z = 0; w = 1; SetToSlerp(p, q, t); } public Quaternion(Matrix3 mat) { x = y = z = 0; w = 1; SetFromRotationMatrix(mat); } static public readonly Quaternion Zero = new Quaternion(0.0f, 0.0f, 0.0f, 0.0f); static public readonly Quaternion Identity = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); public float this[int key] { get { if (key == 0) return x; else if (key == 1) return y; else if (key == 2) return z; else return w; } set { if (key == 0) x = value; else if (key == 1) y = value; else if (key == 2) z = value; else w = value; } } public float LengthSquared { get { return x * x + y * y + z * z + w * w; } } public float Length { get { return (float)Math.Sqrt(x * x + y * y + z * z + w * w); } } public float Normalize(float epsilon = 0) { float length = Length; if (length > epsilon) { float invLength = 1.0f / length; x *= invLength; y *= invLength; z *= invLength; w *= invLength; } else { length = 0; x = y = z = w = 0; } return length; } public Quaternion Normalized { get { Quaternion q = new Quaternion(this); q.Normalize(); return q; } } public float Dot(Quaternion q2) { return x * q2.x + y * q2.y + z * q2.z + w * q2.w; } public static Quaternion operator *(Quaternion a, Quaternion b) { float w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z; float x = a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y; float y = a.w * b.y + a.y * b.w + a.z * b.x - a.x * b.z; float z = a.w * b.z + a.z * b.w + a.x * b.y - a.y * b.x; return new Quaternion(x, y, z, w); } public static Quaternion operator -(Quaternion q1, Quaternion q2) { return new Quaternion(q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w); } public static Vector3 operator *(Quaternion q, Vector3 v) { //return q.ToRotationMatrix() * v; // inline-expansion of above: float twoX = 2 * q.x; float twoY = 2 * q.y; float twoZ = 2 * q.z; float twoWX = twoX * q.w; float twoWY = twoY * q.w; float twoWZ = twoZ * q.w; float twoXX = twoX * q.x; float twoXY = twoY * q.x; float twoXZ = twoZ * q.x; float twoYY = twoY * q.y; float twoYZ = twoZ * q.y; float twoZZ = twoZ * q.z; return new Vector3( v.x * (1 - (twoYY + twoZZ)) + v.y * (twoXY - twoWZ) + v.z * (twoXZ + twoWY), v.x * (twoXY + twoWZ) + v.y * (1 - (twoXX + twoZZ)) + v.z * (twoYZ - twoWX), v.x * (twoXZ - twoWY) + v.y * (twoYZ + twoWX) + v.z * (1 - (twoXX + twoYY))); ; } /// Inverse() * v public Vector3 InverseMultiply(ref Vector3 v) { float norm = LengthSquared; if (norm > 0) { float invNorm = 1.0f / norm; float qx = -x * invNorm, qy = -y * invNorm, qz = -z * invNorm, qw = w * invNorm; float twoX = 2 * qx; float twoY = 2 * qy; float twoZ = 2 * qz; float twoWX = twoX * qw; float twoWY = twoY * qw; float twoWZ = twoZ * qw; float twoXX = twoX * qx; float twoXY = twoY * qx; float twoXZ = twoZ * qx; float twoYY = twoY * qy; float twoYZ = twoZ * qy; float twoZZ = twoZ * qz; return new Vector3( v.x * (1 - (twoYY + twoZZ)) + v.y * (twoXY - twoWZ) + v.z * (twoXZ + twoWY), v.x * (twoXY + twoWZ) + v.y * (1 - (twoXX + twoZZ)) + v.z * (twoYZ - twoWX), v.x * (twoXZ - twoWY) + v.y * (twoYZ + twoWX) + v.z * (1 - (twoXX + twoYY))); } else return Vector3.zero; } // these multiply quaternion by (1,0,0), (0,1,0), (0,0,1), respectively. // faster than full multiply, because of all the zeros public Vector3 AxisX { get { float twoY = 2 * y; float twoZ = 2 * z; float twoWY = twoY * w; float twoWZ = twoZ * w; float twoXY = twoY * x; float twoXZ = twoZ * x; float twoYY = twoY * y; float twoZZ = twoZ * z; return new Vector3(1 - (twoYY + twoZZ), twoXY + twoWZ, twoXZ - twoWY); } } public Vector3 AxisY { get { float twoX = 2 * x; float twoY = 2 * y; float twoZ = 2 * z; float twoWX = twoX * w; float twoWZ = twoZ * w; float twoXX = twoX * x; float twoXY = twoY * x; float twoYZ = twoZ * y; float twoZZ = twoZ * z; return new Vector3(twoXY - twoWZ, 1 - (twoXX + twoZZ), twoYZ + twoWX); } } public Vector3 AxisZ { get { float twoX = 2 * x; float twoY = 2 * y; float twoZ = 2 * z; float twoWX = twoX * w; float twoWY = twoY * w; float twoXX = twoX * x; float twoXZ = twoZ * x; float twoYY = twoY * y; float twoYZ = twoZ * y; return new Vector3(twoXZ + twoWY, twoYZ - twoWX, 1 - (twoXX + twoYY)); } } public Quaternion Inverse() { float norm = LengthSquared; if (norm > 0) { float invNorm = 1.0f / norm; return new Quaternion( -x * invNorm, -y * invNorm, -z * invNorm, w * invNorm); } else return Quaternion.Zero; } public static Quaternion Inverse(Quaternion q) { return q.Inverse(); } public Matrix3 ToRotationMatrix() { float twoX = 2 * x; float twoY = 2 * y; float twoZ = 2 * z; float twoWX = twoX * w; float twoWY = twoY * w; float twoWZ = twoZ * w; float twoXX = twoX * x; float twoXY = twoY * x; float twoXZ = twoZ * x; float twoYY = twoY * y; float twoYZ = twoZ * y; float twoZZ = twoZ * z; Matrix3 m = Matrix3.Zero; m[0, 0] = 1 - (twoYY + twoZZ); m[0, 1] = twoXY - twoWZ; m[0, 2] = twoXZ + twoWY; m[1, 0] = twoXY + twoWZ; m[1, 1] = 1 - (twoXX + twoZZ); m[1, 2] = twoYZ - twoWX; m[2, 0] = twoXZ - twoWY; m[2, 1] = twoYZ + twoWX; m[2, 2] = 1 - (twoXX + twoYY); return m; } public void SetAxisAngleD(Vector3 axis, float AngleDeg) { double angle_rad = MathUtil.Deg2Rad * AngleDeg; double halfAngle = 0.5 * angle_rad; double sn = Math.Sin(halfAngle); w = (float)Math.Cos(halfAngle); x = (float)(sn * axis.x); y = (float)(sn * axis.y); z = (float)(sn * axis.z); } public static Quaternion AngleAxis(float angleDeg, Vector3 axis) { return new Quaternion(axis, angleDeg); } public static Quaternion AngleAxisRad(float angleRad, Vector3 axis) { return new Quaternion(axis, angleRad * MathUtil.Rad2Degf); } // this function can take non-normalized vectors vFrom and vTo (normalizes internally) public void SetFromTo(Vector3 vFrom, Vector3 vTo) { // [TODO] this page seems to have optimized version: // http://lolengine.net/blog/2013/09/18/beautiful-maths-quaternion-from-vectors // [RMS] not ideal to explicitly normalize here, but if we don't, // output quaternion is not normalized and this causes problems, // eg like drift if we do repeated SetFromTo() Vector3 from = vFrom.normalized, to = vTo.normalized; Vector3 bisector = (from + to).normalized; w = from.Dot(bisector); if (w != 0) { Vector3 cross = from.Cross(bisector); x = cross.x; y = cross.y; z = cross.z; } else { float invLength; if (Math.Abs(from.x) >= Math.Abs(from.y)) { // V1.x or V1.z is the largest magnitude component. invLength = (float)(1.0 / Math.Sqrt(from.x * from.x + from.z * from.z)); x = -from.z * invLength; y = 0; z = +from.x * invLength; } else { // V1.y or V1.z is the largest magnitude component. invLength = (float)(1.0 / Math.Sqrt(from.y * from.y + from.z * from.z)); x = 0; y = +from.z * invLength; z = -from.y * invLength; } } Normalize(); // aaahhh just to be safe... } public static Quaternion FromTo(Vector3 vFrom, Vector3 vTo) { return new Quaternion(vFrom, vTo); } public static Quaternion FromToConstrained(Vector3 vFrom, Vector3 vTo, Vector3 vAround) { float fAngle = MathUtil.PlaneAngleSignedD(vFrom, vTo, vAround); return Quaternion.AngleAxis(fAngle, vAround); } public void SetToSlerp(Quaternion p, Quaternion q, float t) { float cs = p.Dot(q); float angle = (float)Math.Acos(cs); if (Math.Abs(angle) >= MathUtil.ZeroTolerance) { float sn = (float)Math.Sin(angle); float invSn = 1 / sn; float tAngle = t * angle; float coeff0 = (float)Math.Sin(angle - tAngle) * invSn; float coeff1 = (float)Math.Sin(tAngle) * invSn; x = coeff0 * p.x + coeff1 * q.x; y = coeff0 * p.y + coeff1 * q.y; z = coeff0 * p.z + coeff1 * q.z; w = coeff0 * p.w + coeff1 * q.w; } else { x = p.x; y = p.y; z = p.z; w = p.w; } } public static Quaternion Slerp(Quaternion p, Quaternion q, float t) { return new Quaternion(p, q, t); } public void SetFromRotationMatrix(Matrix3 rot) { // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes // article "Quaternion Calculus and Fast Animation". Index3 next = new Index3(1, 2, 0); float trace = rot[0, 0] + rot[1, 1] + rot[2, 2]; float root; if (trace > 0) { // |w| > 1/2, may as well choose w > 1/2 root = (float)Math.Sqrt(trace + (float)1); // 2w w = ((float)0.5) * root; root = ((float)0.5) / root; // 1/(4w) x = (rot[2, 1] - rot[1, 2]) * root; y = (rot[0, 2] - rot[2, 0]) * root; z = (rot[1, 0] - rot[0, 1]) * root; } else { // |w| <= 1/2 int i = 0; if (rot[1, 1] > rot[0, 0]) { i = 1; } if (rot[2, 2] > rot[i, i]) { i = 2; } int j = next[i]; int k = next[j]; root = (float)Math.Sqrt(rot[i, i] - rot[j, j] - rot[k, k] + (float)1); Vector3 quat = new Vector3(x, y, z); quat[i] = ((float)0.5) * root; root = ((float)0.5) / root; w = (rot[k, j] - rot[j, k]) * root; quat[j] = (rot[j, i] + rot[i, j]) * root; quat[k] = (rot[k, i] + rot[i, k]) * root; x = quat.x; y = quat.y; z = quat.z; } Normalize(); // we prefer normalized quaternions... } public static Quaternion Euler(Vector3 euler) { float pitch = euler.x; float roll = euler.y; float yaw = euler.z; Quaternion q; // Abbreviations for the various angular functions double cy = Math.Cos(yaw * 0.5); double sy = Math.Sin(yaw * 0.5); double cr = Math.Cos(roll * 0.5); double sr = Math.Sin(roll * 0.5); double cp = Math.Cos(pitch * 0.5); double sp = Math.Sin(pitch * 0.5); q.w = (float)(cy * cr * cp + sy * sr * sp); q.x = (float)(cy * sr * cp - sy * cr * sp); q.y = (float)(cy * cr * sp + sy * sr * cp); q.z = (float)(sy * cr * cp - cy * sr * sp); return q; } public static bool operator ==(Quaternion a, Quaternion b) { return (a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w); } public static bool operator !=(Quaternion a, Quaternion b) { return (a.x != b.x || a.y != b.y || a.z != b.z || a.w != b.w); } public override bool Equals(object obj) { return this == (Quaternion)obj; } public override int GetHashCode() { unchecked // Overflow is fine, just wrap { int hash = (int)2166136261; // Suitable nullity checks etc, of course :) hash = (hash * 16777619) ^ x.GetHashCode(); hash = (hash * 16777619) ^ y.GetHashCode(); hash = (hash * 16777619) ^ z.GetHashCode(); hash = (hash * 16777619) ^ w.GetHashCode(); return hash; } } public int CompareTo(Quaternion other) { if (x != other.x) return x < other.x ? -1 : 1; else if (y != other.y) return y < other.y ? -1 : 1; else if (z != other.z) return z < other.z ? -1 : 1; else if (w != other.w) return w < other.w ? -1 : 1; return 0; } public bool Equals(Quaternion other) { return (x == other.x && y == other.y && z == other.z && w == other.w); } public bool EpsilonEqual(Quaternion q2, float epsilon) { return (float)Math.Abs(x - q2.x) <= epsilon && (float)Math.Abs(y - q2.y) <= epsilon && (float)Math.Abs(z - q2.z) <= epsilon && (float)Math.Abs(w - q2.w) <= epsilon; } public override string ToString() { return string.Format("{0:F8} {1:F8} {2:F8} {3:F8}", x, y, z, w); } public string ToString(string fmt) { return string.Format("{0} {1} {2} {3}", x.ToString(fmt), y.ToString(fmt), z.ToString(fmt), w.ToString(fmt)); } #if G3_USING_UNITY public static implicit operator Quaternion(Quaternion q) { return new Quaternion(q.x, q.y, q.z, q.w); } public static implicit operator Quaternion(Quaternion q) { return new Quaternion(q.x, q.y, q.z, q.w); } #endif } } ================================================ FILE: SGFCore/G3Lite/Vector2.cs ================================================ using System; namespace SGF.G3Lite { public struct Vector2 : IComparable, IEquatable { public float x; public float y; public Vector2(float f) { x = y = f; } public Vector2(float x, float y) { this.x = x; this.y = y; } public Vector2(float[] v2) { x = v2[0]; y = v2[1]; } public Vector2(double f) { x = y = (float)f; } public Vector2(double x, double y) { this.x = (float)x; this.y = (float)y; } public Vector2(double[] v2) { x = (float)v2[0]; y = (float)v2[1]; } public Vector2(Vector2 copy) { x = copy[0]; y = copy[1]; } static public readonly Vector2 Zero = new Vector2(0.0f, 0.0f); static public readonly Vector2 One = new Vector2(1.0f, 1.0f); static public readonly Vector2 AxisX = new Vector2(1.0f, 0.0f); static public readonly Vector2 AxisY = new Vector2(0.0f, 1.0f); static public readonly Vector2 MaxValue = new Vector2(float.MaxValue, float.MaxValue); static public readonly Vector2 MinValue = new Vector2(float.MinValue, float.MinValue); public float this[int key] { get { return (key == 0) ? x : y; } set { if (key == 0) x = value; else y = value; } } public float LengthSquared { get { return x * x + y * y; } } public float Length { get { return (float)Math.Sqrt(LengthSquared); } } public float Normalize(float epsilon = MathUtil.Epsilonf) { float length = Length; if (length > epsilon) { float invLength = 1.0f / length; x *= invLength; y *= invLength; } else { length = 0; x = y = 0; } return length; } public Vector2 Normalized { get { float length = Length; if (length > MathUtil.Epsilonf) { float invLength = 1 / length; return new Vector2(x * invLength, y * invLength); } else return Vector2.Zero; } } public bool IsNormalized { get { return Math.Abs((x * x + y * y) - 1) < MathUtil.ZeroTolerancef; } } public bool IsFinite { get { float f = x + y; return float.IsNaN(f) == false && float.IsInfinity(f) == false; } } public void Round(int nDecimals) { x = (float)Math.Round(x, nDecimals); y = (float)Math.Round(y, nDecimals); } public float Dot(Vector2 v2) { return x * v2.x + y * v2.y; } public float Cross(Vector2 v2) { return x * v2.y - y * v2.x; } public Vector2 Perp { get { return new Vector2(y, -x); } } public Vector2 UnitPerp { get { return new Vector2(y, -x).Normalized; } } public float DotPerp(Vector2 v2) { return x * v2.y - y * v2.x; } public float AngleD(Vector2 v2) { float fDot = MathUtil.Clamp(Dot(v2), -1, 1); return (float)(Math.Acos(fDot) * MathUtil.Rad2Deg); } public static float AngleD(Vector2 v1, Vector2 v2) { return v1.AngleD(v2); } public float AngleR(Vector2 v2) { float fDot = MathUtil.Clamp(Dot(v2), -1, 1); return (float)(Math.Acos(fDot)); } public static float AngleR(Vector2 v1, Vector2 v2) { return v1.AngleR(v2); } public float DistanceSquared(Vector2 v2) { float dx = v2.x - x, dy = v2.y - y; return dx * dx + dy * dy; } public float Distance(Vector2 v2) { float dx = v2.x - x, dy = v2.y - y; return (float)Math.Sqrt(dx * dx + dy * dy); } public void Set(Vector2 o) { x = o.x; y = o.y; } public void Set(float fX, float fY) { x = fX; y = fY; } public void Add(Vector2 o) { x += o.x; y += o.y; } public void Subtract(Vector2 o) { x -= o.x; y -= o.y; } public static Vector2 operator -(Vector2 v) { return new Vector2(-v.x, -v.y); } public static Vector2 operator +(Vector2 a, Vector2 o) { return new Vector2(a.x + o.x, a.y + o.y); } public static Vector2 operator +(Vector2 a, float f) { return new Vector2(a.x + f, a.y + f); } public static Vector2 operator -(Vector2 a, Vector2 o) { return new Vector2(a.x - o.x, a.y - o.y); } public static Vector2 operator -(Vector2 a, float f) { return new Vector2(a.x - f, a.y - f); } public static Vector2 operator *(Vector2 a, float f) { return new Vector2(a.x * f, a.y * f); } public static Vector2 operator *(float f, Vector2 a) { return new Vector2(a.x * f, a.y * f); } public static Vector2 operator /(Vector2 v, float f) { return new Vector2(v.x / f, v.y / f); } public static Vector2 operator /(float f, Vector2 v) { return new Vector2(f / v.x, f / v.y); } public static Vector2 operator *(Vector2 a, Vector2 b) { return new Vector2(a.x * b.x, a.y * b.y); } public static Vector2 operator /(Vector2 a, Vector2 b) { return new Vector2(a.x / b.x, a.y / b.y); } public static bool operator ==(Vector2 a, Vector2 b) { return (a.x == b.x && a.y == b.y); } public static bool operator !=(Vector2 a, Vector2 b) { return (a.x != b.x || a.y != b.y); } public override bool Equals(object obj) { return this == (Vector2)obj; } public override int GetHashCode() { unchecked // Overflow is fine, just wrap { int hash = (int)2166136261; // Suitable nullity checks etc, of course :) hash = (hash * 16777619) ^ x.GetHashCode(); hash = (hash * 16777619) ^ y.GetHashCode(); return hash; } } public int CompareTo(Vector2 other) { if (x != other.x) return x < other.x ? -1 : 1; else if (y != other.y) return y < other.y ? -1 : 1; return 0; } public bool Equals(Vector2 other) { return (x == other.x && y == other.y); } public bool EpsilonEqual(Vector2 v2, float epsilon) { return (float)Math.Abs(x - v2.x) <= epsilon && (float)Math.Abs(y - v2.y) <= epsilon; } public static Vector2 Lerp(Vector2 a, Vector2 b, float t) { float s = 1 - t; return new Vector2(s * a.x + t * b.x, s * a.y + t * b.y); } public static Vector2 Lerp(ref Vector2 a, ref Vector2 b, float t) { float s = 1 - t; return new Vector2(s * a.x + t * b.x, s * a.y + t * b.y); } public override string ToString() { return string.Format("{0:F8} {1:F8}", x, y); } public static implicit operator Vector2(Vector3 v) { return new Vector2(v.x, v.y); } #if G3_USING_UNITY public static implicit operator Vector2(UnityEngine.Vector2 v) { return new Vector2(v.x, v.y); } public static implicit operator Vector2(Vector2 v) { return new Vector2(v.x, v.y); } #endif } } ================================================ FILE: SGFCore/G3Lite/Vector3.cs ================================================ using System; namespace SGF.G3Lite { public struct Vector3 : IComparable, IEquatable { public float x; public float y; public float z; public Vector3(float f) { x = y = z = f; } public Vector3(float x, float y, float z) { this.x = x; this.y = y; this.z = z; } public Vector3(float[] v2) { x = v2[0]; y = v2[1]; z = v2[2]; } public Vector3(Vector3 copy) { x = copy.x; y = copy.y; z = copy.z; } public Vector3(double f) { x = y = z = (float)f; } public Vector3(double x, double y, double z) { this.x = (float)x; this.y = (float)y; this.z = (float)z; } public Vector3(double[] v2) { x = (float)v2[0]; y = (float)v2[1]; z = (float)v2[2]; } static public readonly Vector3 zero = new Vector3(0.0f, 0.0f, 0.0f); static public readonly Vector3 one = new Vector3(1.0f, 1.0f, 1.0f); static public readonly Vector3 forward = new Vector3(0.0f, 0.0f, 1.0f); static public readonly Vector3 back = new Vector3(0.0f, 0.0f, -1.0f); static public readonly Vector3 up = new Vector3(0.0f, 1.0f, 0.0f); static public readonly Vector3 down = new Vector3(0.0f, -1.0f, 0.0f); static public readonly Vector3 left = new Vector3(-1.0f, 0.0f, 0.0f); static public readonly Vector3 right = new Vector3(1.0f, 0.0f, 0.0f); static public readonly Vector3 OneNormalized = new Vector3(1.0f, 1.0f, 1.0f).normalized; static public readonly Vector3 Invalid = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); static public readonly Vector3 AxisX = new Vector3(1.0f, 0.0f, 0.0f); static public readonly Vector3 AxisY = new Vector3(0.0f, 1.0f, 0.0f); static public readonly Vector3 AxisZ = new Vector3(0.0f, 0.0f, 1.0f); static public readonly Vector3 MaxValue = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); static public readonly Vector3 MinValue = new Vector3(float.MinValue, float.MinValue, float.MinValue); public float this[int key] { get { return (key == 0) ? x : (key == 1) ? y : z; } set { if (key == 0) x = value; else if (key == 1) y = value; else z = value; } } public Vector2 xy { get { return new Vector2(x, y); } set { x = value.x; y = value.y; } } public Vector2 xz { get { return new Vector2(x, z); } set { x = value.x; z = value.y; } } public Vector2 yz { get { return new Vector2(y, z); } set { y = value.x; z = value.y; } } public float sqrMagnitude { get { return x * x + y * y + z * z; } } public float magnitude { get { return (float)Math.Sqrt(sqrMagnitude); } } public float LengthL1 { get { return Math.Abs(x) + Math.Abs(y) + Math.Abs(z); } } public float Max { get { return Math.Max(x, Math.Max(y, z)); } } public float Min { get { return Math.Min(x, Math.Min(y, z)); } } public float MaxAbs { get { return Math.Max(Math.Abs(x), Math.Max(Math.Abs(y), Math.Abs(z))); } } public float MinAbs { get { return Math.Min(Math.Abs(x), Math.Min(Math.Abs(y), Math.Abs(z))); } } public float Normalize(float epsilon = MathUtil.Epsilonf) { float length = magnitude; if (length > epsilon) { float invLength = 1.0f / length; x *= invLength; y *= invLength; z *= invLength; } else { length = 0; x = y = z = 0; } return length; } public Vector3 normalized { get { float length = magnitude; if (length > MathUtil.Epsilonf) { float invLength = 1 / length; return new Vector3(x * invLength, y * invLength, z * invLength); } else return Vector3.zero; } } public bool IsNormalized { get { return Math.Abs((x * x + y * y + z * z) - 1) < MathUtil.ZeroTolerancef; } } public bool IsFinite { get { float f = x + y + z; return float.IsNaN(f) == false && float.IsInfinity(f) == false; } } public void Round(int nDecimals) { x = (float)Math.Round(x, nDecimals); y = (float)Math.Round(y, nDecimals); z = (float)Math.Round(z, nDecimals); } public float Dot(Vector3 v2) { return x * v2[0] + y * v2[1] + z * v2[2]; } public static float Dot(Vector3 v1, Vector3 v2) { return v1.Dot(v2); } public Vector3 Cross(Vector3 v2) { return new Vector3( y * v2.z - z * v2.y, z * v2.x - x * v2.z, x * v2.y - y * v2.x); } public static Vector3 Cross(Vector3 v1, Vector3 v2) { return v1.Cross(v2); } public Vector3 UnitCross(Vector3 v2) { Vector3 n = new Vector3( y * v2.z - z * v2.y, z * v2.x - x * v2.z, x * v2.y - y * v2.x); n.Normalize(); return n; } public float AngleD(Vector3 v2) { float fDot = MathUtil.Clamp(Dot(v2), -1, 1); return (float)(Math.Acos(fDot) * MathUtil.Rad2Deg); } public static float AngleD(Vector3 v1, Vector3 v2) { return v1.AngleD(v2); } public float AngleR(Vector3 v2) { float fDot = MathUtil.Clamp(Dot(v2), -1, 1); return (float)(Math.Acos(fDot)); } public static float AngleR(Vector3 v1, Vector3 v2) { return v1.AngleR(v2); } public float DistanceSquared(Vector3 v2) { float dx = v2.x - x, dy = v2.y - y, dz = v2.z - z; return dx * dx + dy * dy + dz * dz; } public float Distance(Vector3 v2) { float dx = v2.x - x, dy = v2.y - y, dz = v2.z - z; return (float)Math.Sqrt(dx * dx + dy * dy + dz * dz); } public void Set(Vector3 o) { x = o[0]; y = o[1]; z = o[2]; } public void Set(float fX, float fY, float fZ) { x = fX; y = fY; z = fZ; } public void Add(Vector3 o) { x += o[0]; y += o[1]; z += o[2]; } public void Subtract(Vector3 o) { x -= o[0]; y -= o[1]; z -= o[2]; } public static Vector3 operator -(Vector3 v) { return new Vector3(-v.x, -v.y, -v.z); } public static Vector3 operator *(float f, Vector3 v) { return new Vector3(f * v.x, f * v.y, f * v.z); } public static Vector3 operator *(Vector3 v, float f) { return new Vector3(f * v.x, f * v.y, f * v.z); } public static Vector3 operator /(Vector3 v, float f) { return new Vector3(v.x / f, v.y / f, v.z / f); } public static Vector3 operator /(float f, Vector3 v) { return new Vector3(f / v.x, f / v.y, f / v.z); } public static Vector3 operator *(Vector3 a, Vector3 b) { return new Vector3(a.x * b.x, a.y * b.y, a.z * b.z); } public static Vector3 operator /(Vector3 a, Vector3 b) { return new Vector3(a.x / b.x, a.y / b.y, a.z / b.z); } public static Vector3 operator +(Vector3 v0, Vector3 v1) { return new Vector3(v0.x + v1.x, v0.y + v1.y, v0.z + v1.z); } public static Vector3 operator +(Vector3 v0, float f) { return new Vector3(v0.x + f, v0.y + f, v0.z + f); } public static Vector3 operator -(Vector3 v0, Vector3 v1) { return new Vector3(v0.x - v1.x, v0.y - v1.y, v0.z - v1.z); } public static Vector3 operator -(Vector3 v0, float f) { return new Vector3(v0.x - f, v0.y - f, v0.z - f); } public static bool operator ==(Vector3 a, Vector3 b) { return (a.x == b.x && a.y == b.y && a.z == b.z); } public static bool operator !=(Vector3 a, Vector3 b) { return (a.x != b.x || a.y != b.y || a.z != b.z); } public override bool Equals(object obj) { return this == (Vector3)obj; } public override int GetHashCode() { unchecked // Overflow is fine, just wrap { int hash = (int)2166136261; // Suitable nullity checks etc, of course :) hash = (hash * 16777619) ^ x.GetHashCode(); hash = (hash * 16777619) ^ y.GetHashCode(); hash = (hash * 16777619) ^ z.GetHashCode(); return hash; } } public int CompareTo(Vector3 other) { if (x != other.x) return x < other.x ? -1 : 1; else if (y != other.y) return y < other.y ? -1 : 1; else if (z != other.z) return z < other.z ? -1 : 1; return 0; } public bool Equals(Vector3 other) { return (x == other.x && y == other.y && z == other.z); } public bool EpsilonEqual(Vector3 v2, float epsilon) { return (float)Math.Abs(x - v2.x) <= epsilon && (float)Math.Abs(y - v2.y) <= epsilon && (float)Math.Abs(z - v2.z) <= epsilon; } public static Vector3 Lerp(Vector3 a, Vector3 b, float t) { float s = 1 - t; return new Vector3(s * a.x + t * b.x, s * a.y + t * b.y, s * a.z + t * b.z); } public override string ToString() { return string.Format("{0:F8} {1:F8} {2:F8}", x, y, z); } public string ToString(string fmt) { return string.Format("{0} {1} {2}", x.ToString(fmt), y.ToString(fmt), z.ToString(fmt)); } public static implicit operator Vector3(Vector2 v) { return new Vector3(v.x, v.y, 0); } #if G3_USING_UNITY public static implicit operator Vector3(UnityEngine.Vector3 v) { return new Vector3(v.x, v.y, v.z); } public static implicit operator Vector3(Vector3 v) { return new Vector3(v.x, v.y, v.z); } public static implicit operator Color(Vector3 v) { return new Color(v.x, v.y, v.z, 1.0f); } public static implicit operator Vector3(Color c) { return new Vector3(c.r, c.g, c.b); } #endif } } ================================================ FILE: SGFCore/G3Lite/Vector4.cs ================================================ using System; namespace SGF.G3Lite { public struct Vector4 : IComparable, IEquatable { public float x; public float y; public float z; public float w; public Vector4(float f) { x = y = z = w = f; } public Vector4(float x, float y, float z, float w) { this.x = x; this.y = y; this.z = z; this.w = w; } public Vector4(float[] v2) { x = v2[0]; y = v2[1]; z = v2[2]; w = v2[3]; } public Vector4(Vector4 copy) { x = copy.x; y = copy.y; z = copy.z; w = copy.w; } static public readonly Vector4 zero = new Vector4(0.0f, 0.0f, 0.0f, 0.0f); static public readonly Vector4 one = new Vector4(1.0f, 1.0f, 1.0f, 1.0f); public float this[int key] { get { return (key < 2) ? ((key == 0) ? x : y) : ((key == 2) ? z : w); } set { if (key < 2) { if (key == 0) x = value; else y = value; } else { if (key == 2) z = value; else w = value; } } } public float LengthSquared { get { return x * x + y * y + z * z + w * w; } } public float Length { get { return (float)Math.Sqrt(LengthSquared); } } public float LengthL1 { get { return Math.Abs(x) + Math.Abs(y) + Math.Abs(z) + Math.Abs(w); } } public float Normalize(float epsilon = MathUtil.Epsilonf) { float length = Length; if (length > epsilon) { float invLength = 1.0f / length; x *= invLength; y *= invLength; z *= invLength; w *= invLength; } else { length = 0; x = y = z = w = 0; } return length; } public Vector4 Normalized { get { float length = Length; if (length > MathUtil.Epsilon) { float invLength = 1.0f / length; return new Vector4(x * invLength, y * invLength, z * invLength, w * invLength); } else return Vector4.zero; } } public bool IsNormalized { get { return Math.Abs((x * x + y * y + z * z + w * w) - 1) < MathUtil.ZeroTolerance; } } public bool IsFinite { get { float f = x + y + z + w; return float.IsNaN(f) == false && float.IsInfinity(f) == false; } } public void Round(int nDecimals) { x = (float)Math.Round(x, nDecimals); y = (float)Math.Round(y, nDecimals); z = (float)Math.Round(z, nDecimals); w = (float)Math.Round(w, nDecimals); } public float Dot(Vector4 v2) { return x * v2.x + y * v2.y + z * v2.z + w * v2.w; } public float Dot(ref Vector4 v2) { return x * v2.x + y * v2.y + z * v2.z + w * v2.w; } public static float Dot(Vector4 v1, Vector4 v2) { return v1.Dot(v2); } public float AngleD(Vector4 v2) { float fDot = MathUtil.Clamp(Dot(v2), -1, 1); return (float)Math.Acos(fDot) * MathUtil.Rad2Degf; } public static float AngleD(Vector4 v1, Vector4 v2) { return v1.AngleD(v2); } public float AngleR(Vector4 v2) { float fDot = MathUtil.Clamp(Dot(v2), -1, 1); return (float)Math.Acos(fDot); } public static float AngleR(Vector4 v1, Vector4 v2) { return v1.AngleR(v2); } public float DistanceSquared(Vector4 v2) { float dx = v2.x - x, dy = v2.y - y, dz = v2.z - z, dw = v2.w - w; return dx * dx + dy * dy + dz * dz + dw * dw; } public float DistanceSquared(ref Vector4 v2) { float dx = v2.x - x, dy = v2.y - y, dz = v2.z - z, dw = v2.w - w; return dx * dx + dy * dy + dz * dz + dw * dw; } public float Distance(Vector4 v2) { float dx = v2.x - x, dy = v2.y - y, dz = v2.z - z, dw = v2.w - w; return (float)Math.Sqrt(dx * dx + dy * dy + dz * dz + dw * dw); } public float Distance(ref Vector4 v2) { float dx = v2.x - x, dy = v2.y - y, dz = v2.z - z, dw = v2.w - w; return (float)Math.Sqrt(dx * dx + dy * dy + dz * dz + dw * dw); } public static Vector4 operator -(Vector4 v) { return new Vector4(-v.x, -v.y, -v.z, -v.w); } public static Vector4 operator *(float f, Vector4 v) { return new Vector4(f * v.x, f * v.y, f * v.z, f * v.w); } public static Vector4 operator *(Vector4 v, float f) { return new Vector4(f * v.x, f * v.y, f * v.z, f * v.w); } public static Vector4 operator /(Vector4 v, float f) { return new Vector4(v.x / f, v.y / f, v.z / f, v.w / f); } public static Vector4 operator /(float f, Vector4 v) { return new Vector4(f / v.x, f / v.y, f / v.z, f / v.w); } public static Vector4 operator *(Vector4 a, Vector4 b) { return new Vector4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w); } public static Vector4 operator /(Vector4 a, Vector4 b) { return new Vector4(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w); } public static Vector4 operator +(Vector4 v0, Vector4 v1) { return new Vector4(v0.x + v1.x, v0.y + v1.y, v0.z + v1.z, v0.w + v1.w); } public static Vector4 operator +(Vector4 v0, float f) { return new Vector4(v0.x + f, v0.y + f, v0.z + f, v0.w + f); } public static Vector4 operator -(Vector4 v0, Vector4 v1) { return new Vector4(v0.x - v1.x, v0.y - v1.y, v0.z - v1.z, v0.w - v1.w); } public static Vector4 operator -(Vector4 v0, float f) { return new Vector4(v0.x - f, v0.y - f, v0.z - f, v0.w - f); } public static bool operator ==(Vector4 a, Vector4 b) { return (a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w); } public static bool operator !=(Vector4 a, Vector4 b) { return (a.x != b.x || a.y != b.y || a.z != b.z || a.w != b.w); } public override bool Equals(object obj) { return this == (Vector4)obj; } public override int GetHashCode() { unchecked // Overflow is fine, just wrap { int hash = (int)2166136261; // Suitable nullity checks etc, of course :) hash = (hash * 16777619) ^ x.GetHashCode(); hash = (hash * 16777619) ^ y.GetHashCode(); hash = (hash * 16777619) ^ z.GetHashCode(); hash = (hash * 16777619) ^ w.GetHashCode(); return hash; } } public int CompareTo(Vector4 other) { if (x != other.x) return x < other.x ? -1 : 1; else if (y != other.y) return y < other.y ? -1 : 1; else if (z != other.z) return z < other.z ? -1 : 1; else if (w != other.w) return w < other.w ? -1 : 1; return 0; } public bool Equals(Vector4 other) { return (x == other.x && y == other.y && z == other.z && w == other.w); } public bool EpsilonEqual(Vector4 v2, float epsilon) { return Math.Abs(x - v2.x) <= epsilon && Math.Abs(y - v2.y) <= epsilon && Math.Abs(z - v2.z) <= epsilon && Math.Abs(w - v2.w) <= epsilon; } public static implicit operator Vector4(Vector3 v) { return new Vector4(v.x, v.y, v.z, 0.0f); } public static implicit operator Vector3(Vector4 v) { return new Vector3(v.x, v.y, v.z); } public static implicit operator Vector4(Vector2 v) { return new Vector4(v.x, v.y, 0.0f, 0.0f); } public static implicit operator Vector2(Vector4 v) { return new Vector2(v.x, v.y); } public override string ToString() { return string.Format("{0:F8} {1:F8} {2:F8} {3:F8}", x, y, z, w); } public string ToString(string fmt) { return string.Format("{0} {1} {2} {3}", x.ToString(fmt), y.ToString(fmt), z.ToString(fmt), w.ToString(fmt)); } #if G3_USING_UNITY public static implicit operator Vector4(Vector4 v) { return new Vector4(v.x, v.y, v.z, v.w); } public static implicit operator Vector4(Vector4 v) { return new Vector4(v.x, v.y, v.z, v.w); } public static implicit operator Color(Vector4 v) { return new Color(v.x, v.y, v.z, v.w); } public static implicit operator Vector4(Color c) { return new Vector4(c.r, c.g, c.b, c.a); } #endif } } ================================================ FILE: SGFCore/IPCWork/IPCConfig.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 进程通讯模块。 * Inter-process communication module. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System.Collections.Generic; using SGF.Utils; namespace SGF.IPCWork { public class IPCInfo { public int id; public int port; } public class IPCConfig { private readonly static string Path = "./IPCConfig.json"; private readonly static MapList MapIPCInfo = new MapList(); public static IPCInfo GetIPCInfo(int id) { if (MapIPCInfo.Count == 0) { ReadConfig(); } return MapIPCInfo[id]; } private static void ReadConfig() { Debuger.Log(); string jsonStr = FileUtils.ReadString(Path); var obj = MiniJSON.Safe.Json.Deserialize(jsonStr) as List; for (int i = 0; i < obj.Count; i++) { var infoJson = obj[i] as Dictionary; IPCInfo info = new IPCInfo(); info.id = (int)(long)infoJson["id"]; info.port = (int)(long)infoJson["port"]; MapIPCInfo.Add(info.id, info); } } } } ================================================ FILE: SGFCore/IPCWork/IPCManager.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 进程通讯模块。 * 它基于UdpSocket实现,以RPC的方式进行调用。 * 由于是基于Udp的简单实现,所以对单次通讯的数据大小有要求,不能超过当前系统的MTU。 * 如果需要在进程间进行大数据通讯,可以使用Network模块,建立可靠UDP连接,或者TCP连接。 * 当然也可以采用共享内存和管道方案,期待后续有人来完善。 * Inter-process communication module. * It is based on UdpSocket implementation and is called in RPC mode.  * Since it is based on a simple implementation of Udp, there is a requirement for the data size of a single communication and cannot exceed the MTU of the current system.  * If you need to perform big data communication between processes, you can use the Network module to establish a reliable UDP connection or a TCP connection.  * Of course you can also use shared memory and pipeline solutions and look forward to follow-up improvements. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Reflection; using System.Threading; using SGF.Codec; using SGF.Network; using SGF.Network.Core.RPCLite; using SGF.Extension; namespace SGF.IPCWork { public class IPCManager { private int m_id; private int m_port; private Socket m_SystemSocket; private Thread m_ThreadRecv; private byte[] m_RecvBufferTemp = new byte[4096]; private Queue m_RecvBufferQueue = new Queue(); private bool m_IsRunning = false; //RPC private RPCManagerBase m_rpc; public void Init(int id) { m_id = id; m_port = IPCConfig.GetIPCInfo(id).port; m_rpc = new RPCManagerBase(); m_rpc.Init(); } public void Clean() { Stop(); if (m_rpc != null) { m_rpc.Clean(); m_rpc = null; } } public void Dump() { m_rpc.Dump(); } public bool IsRunning { get { return m_IsRunning; } } public void Start() { Debuger.Log(); try { m_SystemSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); m_SystemSocket.Bind(IPUtils.GetIPEndPointAny(AddressFamily.InterNetwork, m_port)); m_port = (m_SystemSocket.LocalEndPoint as IPEndPoint).Port; m_IsRunning = true; m_ThreadRecv = new Thread(Thread_Recv) { IsBackground = true }; m_ThreadRecv.Start(); } catch (Exception e) { Debuger.LogError(e.Message + e.StackTrace); Stop(); } } public void Stop() { Debuger.Log(); m_IsRunning = false; if (m_ThreadRecv != null) { m_ThreadRecv.Interrupt(); m_ThreadRecv = null; } if (m_SystemSocket != null) { try { m_SystemSocket.Shutdown(SocketShutdown.Both); } catch (Exception e) { Debuger.LogWarning(e.Message + e.StackTrace); } m_SystemSocket.Close(); m_SystemSocket = null; } } //================================================================================= //发送逻辑 //================================================================================= private void SendMessage(int dst, byte[] bytes, int len) { m_hasSocketException = false; int dstPort = IPCConfig.GetIPCInfo(dst).port; IPEndPoint ep = IPUtils.GetHostEndPoint("127.0.0.1", dstPort); m_SystemSocket.SendTo(bytes, 0, len, SocketFlags.None, ep); } //================================================================================= //接收逻辑 //================================================================================= private bool m_hasSocketException = false; private void Thread_Recv() { while (m_IsRunning) { try { DoReceiveInThread(); if (m_hasSocketException) { m_hasSocketException = false; Debuger.LogWarning("连接异常已经恢复"); } } catch (SocketException se) { if (!m_hasSocketException) { m_hasSocketException = true; } Debuger.LogWarning("SocketErrorCode:{0}, {1}", se.SocketErrorCode, se.Message); Thread.Sleep(1); } catch (Exception e) { Debuger.LogWarning(e.Message + "\n" + e.StackTrace); Thread.Sleep(1); } } Debuger.LogWarning("End!"); } private void DoReceiveInThread() { EndPoint remotePoint = IPUtils.GetIPEndPointAny(AddressFamily.InterNetwork, 0); int cnt = m_SystemSocket.ReceiveFrom(m_RecvBufferTemp, m_RecvBufferTemp.Length, SocketFlags.None, ref remotePoint); if (cnt > 0) { byte[] dst = new byte[cnt]; Buffer.BlockCopy(m_RecvBufferTemp, 0, dst, 0, cnt); lock (m_RecvBufferQueue) { m_RecvBufferQueue.Enqueue(dst); } } } private void DoReceiveInMain() { lock (m_RecvBufferQueue) { while (m_RecvBufferQueue.Count > 0) { byte[] buffer = m_RecvBufferQueue.Dequeue(); IPCMessage msg = PBSerializer.NDeserialize(buffer); HandleMessage(msg); } } } public void Tick() { DoReceiveInMain(); } //======================================================================== //RPC的协议处理方式 //======================================================================== private string m_currInvokingName; private int m_currInvokingSrc; public void AddRPCListener(object listener) { m_rpc.RegisterListener(listener); } public void RemoveRPCListener(object listener) { m_rpc.UnRegisterListener(listener); } private void HandleMessage(IPCMessage msg) { RPCMessage rpcmsg = msg.rpc; Debuger.Log("[{0}]-> {1}({2})", msg.src, rpcmsg.name, rpcmsg.args.ToListString()); var helper = m_rpc.GetMethodHelper(rpcmsg.name); if (helper != null) { object[] args = new object[rpcmsg.args.Length +1]; List raw_args = rpcmsg.raw_args; ParameterInfo[] paramInfo = helper.method.GetParameters(); if (args.Length == paramInfo.Length) { for (int i = 0; i < raw_args.Count; i++) { if (raw_args[i].type == RPCArgType.PBObject) { args[i + 1] = PBSerializer.NDeserialize(raw_args[i].raw_value, paramInfo[i + 1].ParameterType); } else { args[i + 1] = raw_args[i].value; } } args[0] = msg.src; m_currInvokingName = rpcmsg.name; m_currInvokingSrc = msg.src; try { helper.method.Invoke(helper.listener, BindingFlags.NonPublic, null, args, null); } catch (Exception e) { Debuger.LogError("RPC调用出错:{0}\n{1}", e.Message, e.StackTrace); } m_currInvokingName = ""; m_currInvokingSrc = 0; } else { Debuger.LogWarning("参数数量不一致!"); } } else { Debuger.LogWarning("RPC不存在!"); } } public void Return(params object[] args) { var name = "On" + m_currInvokingName; Debuger.Log("->[{0}] {1}({2})", m_currInvokingSrc, name, args.ToListString()); RPCMessage rpcmsg = new RPCMessage(); rpcmsg.name = name; rpcmsg.args = args; IPCMessage msg = new IPCMessage(); msg.src = m_id; msg.rpc = rpcmsg; byte[] temp = PBSerializer.NSerialize(msg); SendMessage(m_currInvokingSrc, temp, temp.Length); } public void ReturnError(string errinfo, int errcode = 1) { var name = "On" + m_currInvokingName + "Error"; Debuger.LogWarning("->[{0}] {1}({2},{3})", m_currInvokingSrc, name, errinfo, errcode); RPCMessage rpcmsg = new RPCMessage(); rpcmsg.name = name; rpcmsg.args = new object[] { errinfo, errcode }; IPCMessage msg = new IPCMessage(); msg.src = m_id; msg.rpc = rpcmsg; byte[] temp = PBSerializer.NSerialize(msg); SendMessage(m_currInvokingSrc, temp, temp.Length); } public void Invoke(int dst, string name, params object[] args) { Debuger.Log("->[{0}] {1}({2})", dst, name, args.ToListString()); RPCMessage rpcmsg = new RPCMessage(); rpcmsg.name = name; rpcmsg.args = args; IPCMessage msg = new IPCMessage(); msg.src = m_id; msg.rpc = rpcmsg; byte[] temp = PBSerializer.NSerialize(msg); SendMessage(dst, temp, temp.Length); } } } ================================================ FILE: SGFCore/IPCWork/IPCMessage.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 进程通讯模块。 * Inter-process communication module. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using ProtoBuf; using SGF.Network.Core.RPCLite; namespace SGF.IPCWork { [ProtoContract] public class IPCMessage { [ProtoMember(1)] public int src;//源服务模块ID [ProtoMember(2)] public RPCMessage rpc; } } ================================================ FILE: SGFCore/Marshals/MarshalArray.cs ================================================ //////////////////////////////////////////////////////////////////// // _ooOoo_ // // o8888888o // // 88" . "88 // // (| ^_^ |) // // O\ = /O // // ____/`---'\____ // // .' \\| |// `. // // / \\||| : |||// \ // // / _||||| -:- |||||- \ // // | | \\\ - /// | | // // | \_| ''\---/'' | | // // \ .-\__ `-` ___/-. / // // ___`. .' /--.--\ `. . ___ // // ."" '< `.___\_<|>_/___.' >'"". // // | | : `- \`.;`\ _ /`;.`/ - ` : | | // // \ \ `-. \_ __\ /__ _/ .-` / / // // ========`-.____`-.___\_____/___.-`____.-'======== // // `=---=' // // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // // 佛祖保佑 无BUG 不修改 // //////////////////////////////////////////////////////////////////// /* * 描述: * 作者:slicol */ using System; using System.Collections; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace SGF.Marshals { public class MarshalArray : MarshalArrayBase, IEnumerable, IEnumerable where T : struct { public MarshalArray(int length) : base(length, typeof(T)) { } public T this[int index] { get { return GetValue(index); } set { SetValue(index, value); } } public IEnumerator GetEnumerator() { return new Enumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } struct Enumerator : IEnumerator { private MarshalArray list; private int index; private T current; internal Enumerator(MarshalArray list) { this.list = list; this.index = 0; this.current = default(T); } public void Dispose() { } public bool MoveNext() { MarshalArray list = this.list; if ((uint)this.index >= (uint)list.Length) { this.index = this.list.Length + 1; this.current = default(T); return false; } this.current = list[this.index]; ++this.index; return true; } public T Current { get { return this.current; } } object IEnumerator.Current { get { if (this.index == 0 || this.index == this.list.Length + 1) { throw new InvalidOperationException("InvalidOperation_EnumOpCantHappen"); } return (object)this.Current; } } void IEnumerator.Reset() { this.index = 0; this.current = default(T); } } } public abstract class MarshalArrayBase : IDisposable { public static long TotalMemory { get; private set; } private static readonly List ms_cache = new List(); [MethodImpl(MethodImplOptions.Synchronized)] public static void Cleanup() { foreach (var item in ms_cache) { item.Dispose(); } ms_cache.Clear(); } protected IntPtr m_header; protected int m_length; protected int m_elementSize; protected bool m_disposed = false; protected Type m_elementType; [MethodImpl(MethodImplOptions.Synchronized)] protected MarshalArrayBase(int length, Type type) { m_length = length; m_elementType = type; m_elementSize = Marshal.SizeOf(m_elementType); int memSize = m_length * m_elementSize; m_header = Marshal.AllocHGlobal(memSize); TotalMemory += memSize; ms_cache.Add(this); } ~MarshalArrayBase() { Dispose(); } protected void Dispose(bool disposing) { if (m_disposed) { return; } if (m_header != IntPtr.Zero) { TotalMemory -= m_length * m_elementSize; Marshal.FreeHGlobal(m_header); m_length = 0; m_header = IntPtr.Zero; } m_disposed = true; } public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } public int Length { get { return m_length; } } public int ElementSize { get { return m_elementSize; } } public Type ElementType { get { return m_elementType; } } public int ByteLength { get { return m_length * m_elementSize; } } public unsafe void* Pointer { get { return (void*)m_header; } } public IntPtr Ptr { get { return m_header; } } public unsafe void* GetElementPointer(int index) { return (void*)((byte*)m_header + index * m_elementSize); } public unsafe IntPtr GetElementPtr(int index) { return (IntPtr)((byte*)m_header + index * m_elementSize); } public unsafe T GetValue(int index) { if (index < 0 || index >= m_length) { throw new IndexOutOfRangeException("index is out of range"); } var ptrSrc = ((byte*)m_header + index * m_elementSize); return (T)Marshal.PtrToStructure((IntPtr) ptrSrc, m_elementType); } public unsafe void SetValue(int index, T value) { if (index < 0 || index >= m_length) { throw new IndexOutOfRangeException("index is out of range"); } var ptrSrc = ((byte*)m_header + index * m_elementSize); Marshal.StructureToPtr(value, (IntPtr)ptrSrc, true); } public static int IndexOf(MarshalArrayBase source, T item, int beginIndex, int count) { if (beginIndex < 0 || count < 0) { throw new ArgumentException("beginIndex < 0 or count < 0"); } if (source.Length - beginIndex < count) { count = source.Length - beginIndex; } int end = beginIndex + count; int i = beginIndex; while (i < end) { if (source.GetValue(i).Equals(item)) { return i; } ++i; } return -1; } public static int LastIndexOf(MarshalArrayBase source, T item, int beginIndex, int count) { if (beginIndex < 0 || count < 0) { throw new ArgumentException("beginIndex < 0 or count < 0"); } if (beginIndex >= source.Length) { beginIndex = source.Length - 1; } if (beginIndex + 1 < count) { count = beginIndex + 1; } int end = beginIndex - count; int i = beginIndex; while (i > end) { if (source.GetValue(i).Equals(item)) { return i; } --i; } return -1; } public static int Copy(MarshalArrayBase source, int sourceOffset, T[] destination, int destOffset, int count) { if (sourceOffset < 0 || destOffset < 0 || count < 0) { throw new ArgumentException("sourceOffset < 0 or destOffset < 0 or count < 0"); } if (source.Length - sourceOffset < count) { count = source.Length - sourceOffset; } if (destination.Length - destOffset < count) { count = destination.Length - destOffset; } int srcIndex = sourceOffset; int dstIndex = destOffset; int srcEnd = sourceOffset + count; while (srcIndex < srcEnd) { destination[dstIndex] = source.GetValue(srcIndex); ++dstIndex; ++srcIndex; } return count; } public static int Copy(T[] source, int sourceOffset, MarshalArrayBase destination, int destOffset, int count) { if (sourceOffset < 0 || destOffset < 0 || count < 0) { throw new ArgumentException("sourceOffset < 0 or destOffset < 0 or count < 0"); } if (source.Length - sourceOffset < count) { count = source.Length - sourceOffset; } if (destination.Length - destOffset < count) { count = destination.Length - destOffset; } int srcIndex = sourceOffset; int dstIndex = destOffset; int srcEnd = sourceOffset + count; while (srcIndex < srcEnd) { destination.SetValue(dstIndex, source[srcIndex]); ++dstIndex; ++srcIndex; } return count; } public unsafe static int Copy(MarshalArrayBase source, int sourceOffset, MarshalArrayBase destination, int destOffset, int count) { if (sourceOffset < 0 || destOffset < 0 || count < 0) { throw new ArgumentException("sourceOffset < 0 or destOffset < 0 or count < 0"); } if (source.Length - sourceOffset < count) { count = source.Length - sourceOffset; } if (destination.Length - destOffset < count) { count = destination.Length - destOffset; } return CopyBytes(source.Ptr, source.m_elementSize * sourceOffset, destination.Ptr, destination.m_elementSize * destOffset, source.m_elementSize * count); } public unsafe static int CopyBytes(IntPtr source, int sourceOffset, IntPtr destination, int destOffset, int count) { if (source == IntPtr.Zero) { throw new ArgumentException("source is null!"); } if (destination == IntPtr.Zero) { throw new ArgumentException("destination is null"); } if (sourceOffset < 0 || destOffset < 0 || count < 0) { throw new ArgumentException("sourceOffset < 0 or destOffset < 0 or count < 0"); } if (count == 0) { return 0; } byte* srcPtr = (byte*)source; srcPtr += sourceOffset; byte* dstPtr = (byte*)destination; dstPtr += destOffset; if (srcPtr == dstPtr) { return count; } int byteSize = count; if (source != destination || srcPtr > dstPtr) { byte* srcEnd = srcPtr + byteSize; while (srcPtr < srcEnd) { *dstPtr = *srcPtr; ++srcPtr; ++dstPtr; } } else { byte* srcEnd = srcPtr - 1; srcPtr = srcPtr + byteSize - 1; dstPtr = dstPtr + byteSize - 1; while (srcPtr > srcEnd) { *dstPtr = *srcPtr; --srcPtr; --dstPtr; } } return count; } } } ================================================ FILE: SGFCore/Marshals/MarshalList.cs ================================================ //参照System.Collections.Generic.List实现的 using System; using System.Collections; using System.Collections.Generic; using System.Threading; using SGF.Utils; namespace SGF.Marshals { public unsafe class MarshalList : IList, IList, IDisposable where T : struct { private MarshalArray m_items; private int m_size; private int m_version; private object m_syncRoot; public MarshalList() { this.m_items = new MarshalArray(4); } public MarshalList(int capacity) { if (capacity < 0) { throw new ArgumentException("CapacityStep不能小于0!"); } this.m_items = new MarshalArray(capacity); } public void Dispose() { m_items.Dispose(); } public int Capacity { get { return m_items.Length; } set { if (value == m_items.Length) return; if (value < this.m_size) { throw new ArgumentException("新的Capacity不能小于已有数据长度!"); } if (value > 0) { var objArray = new MarshalArray(value); if (this.m_size > 0) MarshalArrayBase.Copy(this.m_items, 0, objArray, 0, this.m_size); m_items.Dispose(); this.m_items = objArray; } else { m_items.Dispose(); this.m_items = new MarshalArray(4); } } } public int Count { get { return this.m_size; } } private void EnsureCapacity(int min) { if (this.m_items.Length >= min) return; int num = this.m_items.Length == 0 ? 4 : this.m_items.Length * 2; if (num < min) num = min; this.Capacity = num; } public void TrimExcess() { if (this.m_size >= (int)((double)this.m_items.Length * 0.9)) { return; } this.Capacity = this.m_size; } #region ////IList//// bool IList.IsFixedSize { get { return false; } } bool IList.IsReadOnly { get { return false; } } object IList.this[int index] { get { return (object)this[index]; } set { VerifyValueType(value); this[index] = (T)value; } } int IList.Add(object item) { VerifyValueType(item); this.Add((T)item); return this.Count - 1; } bool IList.Contains(object item) { if (IsCompatibleObject(item)) return this.Contains((T)item); return false; } int IList.IndexOf(object item) { if (IsCompatibleObject(item)) return this.IndexOf((T)item); return -1; } void IList.Insert(int index, object item) { VerifyValueType(item); this.Insert(index, (T)item); } void IList.Remove(object item) { if (!IsCompatibleObject(item)) return; this.Remove((T)item); } #endregion #region ////ICollection//// bool ICollection.IsReadOnly { get { return false; } } bool ICollection.IsSynchronized { get { return false; } } object ICollection.SyncRoot { get { if (this.m_syncRoot == null) Interlocked.CompareExchange(ref this.m_syncRoot, new object(), (object)null); return this.m_syncRoot; } } #endregion #region ////IEnumerator//// public IEnumerator GetEnumerator() { return new Enumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(this); } #endregion #region ////取值//// public T this[int index] { get { if ((uint)index >= (uint)this.m_size) { ThrowHelper.ThrowArgumentOutOfRangeException(); } return this.m_items[index]; } set { if ((uint)index >= (uint)this.m_size) { ThrowHelper.ThrowArgumentOutOfRangeException(); } this.m_items[index] = value; ++this.m_version; } } public MarshalList GetRange(int index, int count) { if (index < 0 || count < 0) { ThrowHelper.ThrowArgumentOutOfRangeException( index < 0 ? ExceptionArgument.index : ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); } if (this.m_size - index < count) { ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); } MarshalList objList = new MarshalList(count); MarshalArrayBase.Copy(this.m_items, index, objList.m_items, 0, count); objList.m_size = count; return objList; } public T[] ToArray() { T[] objArray = new T[this.m_size]; MarshalArrayBase.Copy(this.m_items, 0, objArray, 0, this.m_size); return objArray; } public bool Contains(T item) { EqualityComparer equalityComparer = EqualityComparer.Default; for (int index = 0; index < this.m_size; ++index) { if (equalityComparer.Equals(this.m_items[index], item)) return true; } return false; } #endregion #region ////Add/Insert//// public void Add(T item) { if (this.m_size == this.m_items.Length) { this.EnsureCapacity(this.m_size + 1); } this.m_items[this.m_size++] = item; ++this.m_version; } public void AddRange(IEnumerable collection) { this.InsertRange(this.m_size, collection); } public void Insert(int index, T item) { if ((uint)index > (uint)this.m_size) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_ListInsert); if (this.m_size == this.m_items.Length) this.EnsureCapacity(this.m_size + 1); if (index < this.m_size) MarshalArrayBase.Copy(this.m_items, index, this.m_items, index + 1, this.m_size - index); this.m_items[index] = item; ++this.m_size; ++this.m_version; } public void InsertRange(int index, IEnumerable collection) { if (collection == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); if ((uint)index > (uint)this.m_size) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index); ICollection objs = collection as ICollection; if (objs != null) { int count = objs.Count; if (count > 0) { this.EnsureCapacity(this.m_size + count); if (index < this.m_size) MarshalArrayBase.Copy(this.m_items, index, this.m_items, index + count, this.m_size - index); if (this == objs) { MarshalArrayBase.Copy(this.m_items, 0, this.m_items, index, index); MarshalArrayBase.Copy(this.m_items, index + count, this.m_items, index * 2, this.m_size - index); } else { T[] array = new T[count]; objs.CopyTo(array, 0); MarshalArrayBase.Copy(array, 0, m_items, index, count); } this.m_size += count; } } else { foreach (T obj in collection) { this.Insert(index++, obj); } } ++this.m_version; } #endregion #region ////Remove/Clear//// public bool Remove(T item) { int index = this.IndexOf(item); if (index < 0) return false; this.RemoveAt(index); return true; } public void RemoveAt(int index) { if ((uint)index >= (uint)this.m_size) ThrowHelper.ThrowArgumentOutOfRangeException(); --this.m_size; if (index < this.m_size) MarshalArrayBase.Copy(this.m_items, index + 1, this.m_items, index, this.m_size - index); this.m_items[this.m_size] = default(T); ++this.m_version; } public void RemoveRange(int index, int count) { if (index < 0 || count < 0) ThrowHelper.ThrowArgumentOutOfRangeException(index < 0 ? ExceptionArgument.index : ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); if (this.m_size - index < count) ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); if (count <= 0) return; this.m_size -= count; if (index < this.m_size) MarshalArrayBase.Copy(this.m_items, index + count, this.m_items, index, this.m_size - index); //MarshalArrayBase.Clear(this.m_items, this.m_size, count); ++this.m_version; } public void Clear() { //因为是值类型,且非托管 this.m_size = 0; ++this.m_version; } #endregion #region ////CopyTo//// public void CopyTo(T[] array, int arrayIndex) { MarshalArrayBase.Copy(this.m_items, 0, array, arrayIndex, this.m_size); } public void CopyTo(Array array, int index) { MarshalArrayBase.Copy(this.m_items, 0, (T[])array, index, this.m_size); } public void CopyTo(MarshalArray array) { this.CopyTo(array, 0); } public void CopyTo(int index, MarshalArray array, int arrayIndex, int count) { if (this.m_size - index < count) { ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); } MarshalArrayBase.Copy(this.m_items, index, array, arrayIndex, count); } public void CopyTo(MarshalArray array, int arrayIndex) { MarshalArrayBase.Copy(this.m_items, 0, array, arrayIndex, this.m_size); } #endregion #region ////IndexOf//// public int IndexOf(T item) { return MarshalArrayBase.IndexOf(this.m_items, item, 0, this.m_size); } public int IndexOf(T item, int index) { if (index > this.m_size) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index); return MarshalArrayBase.IndexOf(this.m_items, item, index, this.m_size - index); } public int IndexOf(T item, int index, int count) { if (index > this.m_size) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index); if (count < 0 || index > this.m_size - count) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count); return MarshalArrayBase.IndexOf(this.m_items, item, index, count); } public int LastIndexOf(T item) { return this.LastIndexOf(item, this.m_size - 1, this.m_size); } public int LastIndexOf(T item, int index) { if (index >= this.m_size) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index); return this.LastIndexOf(item, index, index + 1); } public int LastIndexOf(T item, int index, int count) { if (this.m_size == 0) return -1; if (index < 0 || count < 0) ThrowHelper.ThrowArgumentOutOfRangeException(index < 0 ? ExceptionArgument.index : ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); if (index >= this.m_size || count > index + 1) ThrowHelper.ThrowArgumentOutOfRangeException(index >= this.m_size ? ExceptionArgument.index : ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_BiggerThanCollection); return MarshalArrayBase.LastIndexOf(this.m_items, item, index, count); } #endregion //-------------------------------------------------------------------- #region ////工具函数//// //-------------------------------------------------------------------- private static bool IsCompatibleObject(object value) { return value is T || value == null && !typeof(T).IsValueType; } private static void VerifyValueType(object value) { if (IsCompatibleObject(value)) return; ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T)); } #endregion //-------------------------------------------------------------------- //枚举器 //-------------------------------------------------------------------- struct Enumerator : IEnumerator { private MarshalList list; private int index; private int version; private T current; internal Enumerator(MarshalList list) { this.list = list; this.index = 0; this.version = list.m_version; this.current = default(T); } public void Dispose() { } public bool MoveNext() { MarshalList list = this.list; if (this.version != list.m_version || (uint)this.index >= (uint)list.m_size) { return this.MoveNextRare(); } this.current = list.m_items[this.index]; ++this.index; return true; } private bool MoveNextRare() { if (this.version != this.list.m_version) { ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); } this.index = this.list.m_size + 1; this.current = default(T); return false; } public T Current { get { return this.current; } } object IEnumerator.Current { get { if (this.index == 0 || this.index == this.list.m_size + 1) { ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen); } return (object)this.Current; } } void IEnumerator.Reset() { if (this.version != this.list.m_version) { ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); } this.index = 0; this.current = default(T); } } } } ================================================ FILE: SGFCore/MathLite/SGFRandom.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 基于LCG的随机数生成算法 * https://en.wikipedia.org/wiki/Linear_congruential_generator * https://stackoverflow.com/questions/4768180/rand-implementation * LCG-based random number generation algorithm * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ namespace SGF.MathLite { public class SGFRandom { #region 默认实例 public static SGFRandom Default = new SGFRandom(); #endregion #region 线性同余参数 //线性同余随机数生成算法 private const int PrimeA = 214013; private const int PrimeB = 2531011; #endregion //归一化 private const float Mask15Bit_1 = 1.0f / 0x7fff; private const int Mask15Bit = 0x7fff; private int m_Value = 0; public int Seed { set { m_Value = value; } get { return m_Value; } } /// /// 采用线性同余算法产生一个0~1之间的随机小数 /// /// public float Rnd() { float val = ((((m_Value = m_Value * PrimeA + PrimeB) >> 16) & Mask15Bit) - 1) * Mask15Bit_1; return (val > 0.99999f ? 0.99999f : val); } public float Range(float min, float max) { return min + Rnd() * (max - min); } public int Range(int min, int max) { return (int)(min + Rnd() * (max - min)); } public float Range(float max) { return Range(0, max); } public int Range(int max) { return Range(0, max); } } } ================================================ FILE: SGFCore/Module/GeneralModule.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 模块管理器 * Module Manager. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System.Reflection; namespace SGF.Module { public class GeneralModule:ModuleBase, ILogTag { private string m_name = ""; public string Name { get { return m_name; } } public string Title; public GeneralModule() { m_name = this.GetType().Name; LOG_TAG = m_name; } /// /// 调用它以创建模块 /// /// public virtual void Create(object args = null) { this.Log("args:{0}", args); } /// /// 调用它以释放模块 /// public override void Release() { base.Release(); this.Log(); } /// /// 当模块收到消息后,对消息进行一些处理 /// /// /// internal void HandleMessage(string msg, object[] args) { this.Log("msg:{0}, args:{1}", msg, args); var mi = this.GetType() .GetMethod(msg, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); if (mi != null) { mi.Invoke(this, BindingFlags.NonPublic, null, args, null); } else { OnModuleMessage(msg, args); } } /// /// 由派生类去实现,用于处理消息 /// /// /// protected virtual void OnModuleMessage(string msg, object[] args) { this.Log("msg:{0}, args{1}", msg, args); } protected virtual void Show(object arg) { this.Log("args:{0}", arg); } public string LOG_TAG { get; protected set; } } } ================================================ FILE: SGFCore/Module/IModuleActivator.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 模块管理器。 * Module Manager. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ namespace SGF.Module { public interface IModuleActivator { GeneralModule CreateInstance(string moduleName); } } ================================================ FILE: SGFCore/Module/ModuleBase.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 模块管理器。 * Module Manager. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ namespace SGF.Module { public abstract class ModuleBase { public virtual void Release() { } } } ================================================ FILE: SGFCore/Module/ModuleManager.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 模块管理器。 * 当项目的规模足够大时,就需要将整个系统划分为若干个模块。 * 这些模块需要一套系统进行管理。 * 它具备很好的扩展性,结合ILRuntime可以实现iOS版本中模块级别的热更新。 * 它实现了模块间的消息通讯,并以此来解耦。 * Module Manager.  * When the size of the project is large enough, the entire system needs to be divided into several modules. * These modules require a system to manage.  * It is very extensible, combined with ILRuntime can achieve module-level hot updates in the iOS version.  * It implements message communication between modules and decouples it. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using SGF.Utils; namespace SGF.Module { public class ModuleManager:Singleton { class MessageObject { public string msg; public object[] args; } private Dictionary m_mapModules; private Dictionary> m_mapCacheMessage; private List m_listModuleActivators; public ModuleManager() { m_mapModules = new Dictionary(); m_mapCacheMessage = new Dictionary>(); m_listModuleActivators = new List(); } public void Init() { Debuger.Log(); } public void Clean() { Debuger.Log(); m_mapCacheMessage.Clear(); foreach (var pair in m_mapModules) { pair.Value.Release(); } m_mapModules.Clear(); m_listModuleActivators.Clear(); } public void RegisterModuleActivator(IModuleActivator activator) { if (!m_listModuleActivators.Contains(activator)) { m_listModuleActivators.Add(activator); } } public GeneralModule CreateModule(string name, object args = null) { Debuger.Log("name = " + name + ", args = " + args); if (HasModule(name)) { Debuger.LogError("The Module<{0}> Has Existed!"); return null; } GeneralModule module = null; for (int i = 0; i < m_listModuleActivators.Count; i++) { module = m_listModuleActivators[i].CreateInstance(name); if (module != null) { break; } } if (module == null) { Debuger.LogError("模块实例化失败!"); return null; } m_mapModules.Add(name, module); module.Create(args); //处理缓存的消息 if (m_mapCacheMessage.ContainsKey(name)) { List list = m_mapCacheMessage[name]; for (int i = 0; i < list.Count; i++) { MessageObject msgobj = list[i]; module.HandleMessage(msgobj.msg, msgobj.args); } m_mapCacheMessage.Remove(name); } return module; } public bool HasModule(string name) { return m_mapModules.ContainsKey(name); } public GeneralModule GetModule(string name) { GeneralModule module = null; m_mapModules.TryGetValue(name, out module); return module; } //============================================================================ //消息机制 //============================================================================ public void SendMessage(string target, string msg, params object[] args) { GeneralModule module = GetModule(target); if (module != null) { module.HandleMessage(msg, args); } else { var list = GetCacheMessageList(target); MessageObject obj = new MessageObject(); obj.msg = msg; obj.args = args; list.Add(obj); } } private List GetCacheMessageList(string target) { List list = null; if (!m_mapCacheMessage.TryGetValue(target, out list)) { list = new List(); m_mapCacheMessage.Add(target, list); } return list; } public void ShowModule(string target, object arg = null) { SendMessage(target, "Show", arg); } } } ================================================ FILE: SGFCore/Module/NativeModuleActivator.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 模块管理器。 * Module Manager. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; namespace SGF.Module { public class NativeModuleActivator:IModuleActivator { private string m_namespace = ""; private string m_assemblyName = ""; public NativeModuleActivator(string _namespace, string assemblyName) { m_namespace = _namespace; m_assemblyName = assemblyName; } public GeneralModule CreateInstance(string moduleName) { var fullname = m_namespace + "." + moduleName; var type = Type.GetType(fullname + "," + m_assemblyName); if (type != null) { return Activator.CreateInstance(type) as GeneralModule; } return null; } } } ================================================ FILE: SGFCore/MvvmLite/MvvmBinding.cs ================================================ using SGF.SEvent; using SGF.Timers; using SGF.Utils; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Text; namespace SGF.MvvmLite { public class MvvmBinding : IDisposable { //==================================================================== #region ////MvvmBinding Async//// private static Timer m_timerAsync; private static List m_listAsyncBinders = new List(); private static void PumpAsyncBinder(Binder binder) { m_listAsyncBinders.Add(binder); PumpAsync(); } private static void PumpAsync() { if(m_timerAsync == null) { m_timerAsync = new Timer(); m_timerAsync.Interval = 1; m_timerAsync.AutoReset = false; m_timerAsync.Elapsed += (sender, e) => TickAsync(); } m_timerAsync.Enabled = true; } private static void TickAsync() { var binders = m_listAsyncBinders.ToArray(); m_listAsyncBinders.Clear(); for (int i = 0; i < binders.Length; ++i) { binders[i].Validate(); } } #endregion //==================================================================== class Binder { private object target; public string src; private FieldInfo field; private PropertyInfo property; public Signal onValidate = new Signal(); public Binder(object target, string src, MemberInfo member) { this.target = target; this.src = src; this.field = member as FieldInfo; this.property = member as PropertyInfo; } public void Validate() { object value = null; if (field != null) { value = field.GetValue(target); } else if(property != null) { value = property.GetValue(target, null); } onValidate.InvokeSafe(value); } public void Clear() { target = null; field = null; property = null; onValidate.RemoveAllListeners(); } } //==================================================================== private bool m_disposed = false; private DictionarySafe m_binders = new DictionarySafe(); public MvvmBinding() { } ~MvvmBinding() { Dispose(); } public void Dispose() { if (m_disposed) return; m_disposed = true; foreach (var pair in m_binders) { pair.Value.Clear(); } m_binders.Clear(); } protected void Validate(string src) { var binder = m_binders[src]; if (binder != null) { binder.Validate(); } } protected void ValidateAsync(string src) { var binder = m_binders[src]; if (binder != null) { PumpAsyncBinder(binder); } } private MemberInfo GetMemberInfo(string src) { var members = this.GetType().GetMembers(); for (int i = 0; i < members.Length; ++i) { var m = members[i]; if (m.Name == src) { return m; } } return null; } public void Bind(string src, Action handler) { var binder = m_binders[src]; if (binder == null) { var member = GetMemberInfo(src); if(member == null) { Debuger.LogError("Bind Error, Member Not Exist: {0}", src); return; } binder = new Binder(this, src, member); m_binders.Add(src, binder); } binder.onValidate.AddListener(handler); } public void UnBind(string src, Action handler) { var binder = m_binders[src]; if (binder == null) { return; } binder.onValidate.RemoveListener(handler); } } } ================================================ FILE: SGFCore/MvvmLite/MvvmCommand.cs ================================================ using SGF.Timers; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace SGF.MvvmLite { public abstract class MvvmCommandBase { //==================================================================== #region ////MvvmCommand Async//// private static Timer m_timerAsync; private static List m_listAsyncCmds = new List(); protected static void PumpAsyncCommand(MvvmCommandBase cmd) { m_listAsyncCmds.Add(cmd); PumpAsync(); } private static void PumpAsync() { if (m_timerAsync == null) { m_timerAsync = new Timer(); m_timerAsync.Interval = 1; m_timerAsync.AutoReset = false; m_timerAsync.Elapsed += (sender, e) => TickAsync(); } m_timerAsync.Enabled = true; } private static void TickAsync() { var cmds = m_listAsyncCmds.ToArray(); m_listAsyncCmds.Clear(); for (int i = 0; i < cmds.Length; ++i) { cmds[i].Execute(); Debuger.LogVerbose("{0} End----------------", cmds[i].GetType().Name); } } #endregion //==================================================================== protected abstract void Execute(); } public class MvvmCommand: MvvmCommandBase where T:MvvmCommandBase, new () { protected MvvmViewModel m_vm; public static void Send(MvvmViewModel vm) { MvvmCommand cmd = (new T()) as MvvmCommand; cmd.m_vm = vm; Debuger.LogVerbose("{0} Begin--------------", typeof(T).Name); cmd.Execute(); Debuger.LogVerbose("{0} End----------------", typeof(T).Name); } public static void SendAsync(MvvmViewModel vm) { MvvmCommand cmd = (new T()) as MvvmCommand; cmd.m_vm = vm; Debuger.LogVerbose("{0} Begin--------------", typeof(T).Name); PumpAsyncCommand(cmd); } protected override void Execute() { throw new NotImplementedException(); } } } ================================================ FILE: SGFCore/MvvmLite/MvvmManager.cs ================================================ using SGF.Timers; using SGF.Utils; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace SGF.MvvmLite { public class MvvmManager : Singleton { public void Init() { } } } ================================================ FILE: SGFCore/MvvmLite/MvvmModel.cs ================================================ using SGF.SEvent; using SGF.Utils; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; namespace SGF.MvvmLite { public class MvvmModel:MvvmBinding { } } ================================================ FILE: SGFCore/MvvmLite/MvvmViewModel.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace SGF.MvvmLite { public class MvvmViewModel: MvvmBinding { protected MvvmModel m_model; public MvvmViewModel(MvvmModel model) { m_model = model; } } } ================================================ FILE: SGFCore/Network/Core/KCP/KCPSocket.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 将KCP与Socket封装在一起,以提供可靠UDP通讯功能 * KCP:https://github.com/skywind3000/kcp * KCP CSharp Port:https://github.com/limpo1989/kcp-csharp * Package KCP with Socket to provide reliable UDP communication * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; namespace SGF.Network.Core { public class KCPSocket { private static readonly DateTime UTCTimeBegin = new DateTime(1970, 1, 1); public static UInt32 GetClockMS() { return (UInt32)(Convert.ToInt64(DateTime.UtcNow.Subtract(UTCTimeBegin).TotalMilliseconds) & 0xffffffff); } public delegate void KCPReceiveListener(byte[] buff, int size, IPEndPoint remotePoint); public string LOG_TAG = "KCPSocket"; private bool m_IsRunning = false; private Socket m_SystemSocket; private IPEndPoint m_LocalEndPoint; private AddressFamily m_AddrFamily; private Thread m_ThreadRecv; private byte[] m_RecvBufferTemp = new byte[4096]; //KCP参数 private List m_ListKcp; private uint m_KcpKey = 0; private KCPReceiveListener m_AnyEPListener; //================================================================================= #region 构造和析构 public KCPSocket(int bindPort, uint kcpKey, AddressFamily family = AddressFamily.InterNetwork) { m_AddrFamily = family; m_KcpKey = kcpKey; m_ListKcp = new List(); m_SystemSocket = new Socket(m_AddrFamily, SocketType.Dgram, ProtocolType.Udp); IPEndPoint ipep = IPUtils.GetIPEndPointAny(m_AddrFamily, bindPort); m_SystemSocket.Bind(ipep); bindPort = (m_SystemSocket.LocalEndPoint as IPEndPoint).Port; LOG_TAG = "KCPSocket[" + bindPort + "-" + kcpKey + "]"; m_IsRunning = true; m_ThreadRecv = new Thread(Thread_Recv) {IsBackground = true}; m_ThreadRecv.Start(); #if UNITY_EDITOR_WIN uint IOC_IN = 0x80000000; uint IOC_VENDOR = 0x18000000; uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12; m_SystemSocket.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null); #endif #if UNITY_EDITOR UnityEditor.EditorApplication.playmodeStateChanged -= OnEditorPlayModeChanged; UnityEditor.EditorApplication.playmodeStateChanged += OnEditorPlayModeChanged; #endif } #if UNITY_EDITOR private void OnEditorPlayModeChanged() { if (UnityEngine.Application.isPlaying == false) { UnityEditor.EditorApplication.playmodeStateChanged -= OnEditorPlayModeChanged; Dispose(); } } #endif public void Dispose() { m_IsRunning = false; m_AnyEPListener = null; if (m_ThreadRecv != null) { m_ThreadRecv.Interrupt(); m_ThreadRecv = null; } int cnt = m_ListKcp.Count; for (int i = 0; i < cnt; i++) { m_ListKcp[i].Dispose(); } m_ListKcp.Clear(); if (m_SystemSocket != null) { try { m_SystemSocket.Shutdown(SocketShutdown.Both); } catch (Exception e) { Debuger.LogWarning(e.Message + e.StackTrace); } m_SystemSocket.Close(); m_SystemSocket = null; } } public void Connect(IPEndPoint remotePoint) { m_SystemSocket.Connect(remotePoint); } public int SelfPort { get{return (m_SystemSocket.LocalEndPoint as IPEndPoint).Port;} } public string SelfIP { get { return IPUtils.SelfIP; } } public IPEndPoint SelfEndPoint { get { if (m_LocalEndPoint == null || m_LocalEndPoint.Address.ToString() != IPUtils.SelfIP) { IPAddress ip = IPAddress.Parse(SelfIP); m_LocalEndPoint = new IPEndPoint(ip, SelfPort); } return m_LocalEndPoint; } } public Socket SystemSocket { get { return m_SystemSocket; } } #endregion //================================================================================= public bool EnableBroadcast { get { return m_SystemSocket.EnableBroadcast; } set { m_SystemSocket.EnableBroadcast = value; } } //================================================================================= #region 管理KCP private bool IsValidKcpIPEndPoint(IPEndPoint ipep) { if (ipep == null || ipep.Port == 0 || ipep.Address.Equals(IPAddress.Any) || ipep.Address.Equals(IPAddress.IPv6Any)) { return false; } return true; } private KCPProxy GetKcp(IPEndPoint ipep, bool autoAdd = true) { if (!IsValidKcpIPEndPoint(ipep)) { return null; } KCPProxy proxy = null; int cnt = m_ListKcp.Count; for (int i = 0; i < cnt; i++) { proxy = m_ListKcp[i]; if (proxy.RemotePoint.Equals(ipep)) { return proxy; } } if (autoAdd) { proxy = new KCPProxy(m_KcpKey, ipep, m_SystemSocket); proxy.AddReceiveListener(OnReceiveAny); m_ListKcp.Add(proxy); } return proxy; } public void CloseKcp(IPEndPoint ipep) { KCPProxy proxy = null; int cnt = m_ListKcp.Count; for (int i = 0; i < cnt; i++) { proxy = m_ListKcp[i]; if (proxy.RemotePoint.Equals(ipep)) { m_ListKcp.RemoveAt(i); break; } } } #endregion //================================================================================= #region 发送逻辑 public bool SendTo(byte[] buffer, int size, IPEndPoint remotePoint) { if (remotePoint.Address == IPAddress.Broadcast) { int cnt = m_SystemSocket.SendTo(buffer, size, SocketFlags.None, remotePoint); return cnt > 0; } else { KCPProxy proxy = GetKcp(remotePoint); if (proxy != null) { return proxy.DoSend(buffer, size); } } return false; } public bool SendTo(string message, IPEndPoint remotePoint) { byte[] buffer = Encoding.UTF8.GetBytes(message); return SendTo(buffer, buffer.Length, remotePoint); } #endregion //================================================================================= #region 主线程驱动 public void Update() { if (m_IsRunning) { //获取时钟 uint current = GetClockMS(); int cnt = m_ListKcp.Count; for (int i = 0; i < cnt; i++) { KCPProxy proxy = m_ListKcp[i]; proxy.Update(current); } } } #endregion //================================================================================= #region 接收逻辑 public void AddReceiveListener(IPEndPoint remotePoint, KCPReceiveListener listener) { KCPProxy proxy = GetKcp(remotePoint); if (proxy != null) { proxy.AddReceiveListener(listener); } else { m_AnyEPListener += listener; } } public void RemoveReceiveListener(IPEndPoint remotePoint, KCPReceiveListener listener) { KCPProxy proxy = GetKcp(remotePoint); if (proxy != null) { proxy.RemoveReceiveListener(listener); } else { m_AnyEPListener -= listener; } } public void AddReceiveListener(KCPReceiveListener listener) { m_AnyEPListener += listener; } public void RemoveReceiveListener(KCPReceiveListener listener) { m_AnyEPListener -= listener; } private void OnReceiveAny(byte[] buffer, int size, IPEndPoint remotePoint) { if (m_AnyEPListener != null) { m_AnyEPListener(buffer, size, remotePoint); } } #endregion //================================================================================= #region 接收线程 private void Thread_Recv() { Debuger.Log("Thread_Recv() Begin ......"); while (m_IsRunning) { try { DoReceive(); } catch (Exception e) { Debuger.LogWarning("Thread_Recv() " + e.Message + "\n" + e.StackTrace); Thread.Sleep(10); } } Debuger.Log("Thread_Recv() End!"); } private void DoReceive() { EndPoint remotePoint = new IPEndPoint(IPAddress.Any, 0); int cnt = m_SystemSocket.ReceiveFrom(m_RecvBufferTemp, m_RecvBufferTemp.Length, SocketFlags.None, ref remotePoint); if (cnt > 0) { KCPProxy proxy = GetKcp((IPEndPoint)remotePoint); if (proxy != null) { proxy.DoReceiveInThread(m_RecvBufferTemp, cnt); } } } #endregion } class KCPProxy { private KCP m_Kcp; private bool m_NeedKcpUpdateFlag = false; private uint m_NextKcpUpdateTime = 0; private SwitchQueue m_RecvQueue = new SwitchQueue(128); private IPEndPoint m_RemotePoint; private Socket m_Socket; private KCPSocket.KCPReceiveListener m_Listener; public IPEndPoint RemotePoint { get { return m_RemotePoint; } } public KCPProxy(uint key, IPEndPoint remotePoint, Socket socket) { m_Socket = socket; m_RemotePoint = remotePoint; m_Kcp = new KCP(key, HandleKcpSend); m_Kcp.NoDelay(1, 10, 2, 1); m_Kcp.WndSize(128, 128); } public void Dispose() { m_Socket = null; NetDebuger.WeakNetCancel(this); if (m_Kcp != null) { m_Kcp.Dispose(); m_Kcp = null; } m_Listener = null; } //--------------------------------------------- private void HandleKcpSend(byte[] buff, int size) { if (NetDebuger.EnableWeakNet) { NetDebuger.WeakNetSimulate(this, buff, size, HandleKcpSend_Hook); } else { if (m_Socket != null) { m_Socket.SendTo(buff, 0, size, SocketFlags.None, m_RemotePoint); } } } private void HandleKcpSend_Hook(byte[] buff, int size) { if (m_Socket != null) { m_Socket.SendTo(buff, 0, size, SocketFlags.None, m_RemotePoint); } } public bool DoSend(byte[] buff, int size) { m_NeedKcpUpdateFlag = true; return m_Kcp.Send(buff, size) >= 0; } //--------------------------------------------- public void AddReceiveListener(KCPSocket.KCPReceiveListener listener) { m_Listener += listener; } public void RemoveReceiveListener(KCPSocket.KCPReceiveListener listener) { m_Listener -= listener; } public void DoReceiveInThread(byte[] buffer, int size) { if (NetDebuger.IsPacketLoss()) { return; } byte[] dst = new byte[size]; Buffer.BlockCopy(buffer, 0, dst, 0, size); m_RecvQueue.Push(dst); } private void HandleRecvQueue() { m_RecvQueue.Switch(); while (!m_RecvQueue.Empty()) { var recvBufferRaw = m_RecvQueue.Pop(); int ret = m_Kcp.Input(recvBufferRaw, recvBufferRaw.Length); //收到的不是一个正确的KCP包 if (ret < 0) { if (m_Listener != null) { m_Listener(recvBufferRaw, recvBufferRaw.Length, m_RemotePoint); } return; } m_NeedKcpUpdateFlag = true; KCP kcp = m_Kcp; for (int size = kcp.PeekSize(); size > 0; size = kcp.PeekSize()) { var recvBuffer = new byte[size]; if (kcp.Recv(recvBuffer) > 0) { if (m_Listener != null) { m_Listener(recvBuffer, size, m_RemotePoint); } } } } } //--------------------------------------------- public void Update(uint currentTimeMS) { HandleRecvQueue(); if (m_NeedKcpUpdateFlag || currentTimeMS >= m_NextKcpUpdateTime) { if (m_Kcp != null) { m_Kcp.Update(currentTimeMS); m_NextKcpUpdateTime = m_Kcp.Check(currentTimeMS); m_NeedKcpUpdateFlag = false; } } } //--------------------------------------------- } } ================================================ FILE: SGFCore/Network/Core/KCP/LICENSE.txt ================================================ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. {description} Copyright (C) {year} {fullname} This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. {signature of Ty Coon}, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. ================================================ FILE: SGFCore/Network/Core/KCP/kcp.cs ================================================ using System; namespace SGF.Network.Core { public class KCP { public const int IKCP_RTO_NDL = 30; // no delay min rto public const int IKCP_RTO_MIN = 100; // normal min rto public const int IKCP_RTO_DEF = 200; public const int IKCP_RTO_MAX = 60000; public const int IKCP_CMD_PUSH = 81; // cmd: push data public const int IKCP_CMD_ACK = 82; // cmd: ack public const int IKCP_CMD_WASK = 83; // cmd: window probe (ask) public const int IKCP_CMD_WINS = 84; // cmd: window size (tell) public const int IKCP_ASK_SEND = 1; // need to send IKCP_CMD_WASK public const int IKCP_ASK_TELL = 2; // need to send IKCP_CMD_WINS public const int IKCP_WND_SND = 32; public const int IKCP_WND_RCV = 32; public const int IKCP_MTU_DEF = 1400; public const int IKCP_ACK_FAST = 3; public const int IKCP_INTERVAL = 100; public const int IKCP_OVERHEAD = 24; public const int IKCP_DEADLINK = 10; public const int IKCP_THRESH_INIT = 2; public const int IKCP_THRESH_MIN = 2; public const int IKCP_PROBE_INIT = 7000; // 7 secs to probe window size public const int IKCP_PROBE_LIMIT = 120000; // up to 120 secs to probe window // encode 8 bits unsigned int public static int ikcp_encode8u(byte[] p, int offset, byte c) { p[0 + offset] = c; return 1; } // decode 8 bits unsigned int public static int ikcp_decode8u(byte[] p, int offset, ref byte c) { c = p[0 + offset]; return 1; } /* encode 16 bits unsigned int (lsb) */ public static int ikcp_encode16u(byte[] p, int offset, UInt16 w) { p[0 + offset] = (byte)(w >> 0); p[1 + offset] = (byte)(w >> 8); return 2; } /* decode 16 bits unsigned int (lsb) */ public static int ikcp_decode16u(byte[] p, int offset, ref UInt16 c) { UInt16 result = 0; result |= (UInt16)p[0 + offset]; result |= (UInt16)(p[1 + offset] << 8); c = result; return 2; } /* encode 32 bits unsigned int (lsb) */ public static int ikcp_encode32u(byte[] p, int offset, UInt32 l) { p[0 + offset] = (byte)(l >> 0); p[1 + offset] = (byte)(l >> 8); p[2 + offset] = (byte)(l >> 16); p[3 + offset] = (byte)(l >> 24); return 4; } /* decode 32 bits unsigned int (lsb) */ public static int ikcp_decode32u(byte[] p, int offset, ref UInt32 c) { UInt32 result = 0; result |= (UInt32)p[0 + offset]; result |= (UInt32)(p[1 + offset] << 8); result |= (UInt32)(p[2 + offset] << 16); result |= (UInt32)(p[3 + offset] << 24); c = result; return 4; } public static byte[] slice(byte[] p, int start, int stop) { var bytes = new byte[stop - start]; Array.Copy(p, start, bytes, 0, bytes.Length); return bytes; } public static T[] slice(T[] p, int start, int stop) { var arr = new T[stop - start]; var index = 0; for (var i = start; i < stop; i++) { arr[index] = p[i]; index++; } return arr; } public static byte[] append(byte[] p, byte c) { var bytes = new byte[p.Length + 1]; Array.Copy(p, bytes, p.Length); bytes[p.Length] = c; return bytes; } public static T[] append(T[] p, T c) { var arr = new T[p.Length + 1]; for (var i = 0; i < p.Length; i++) arr[i] = p[i]; arr[p.Length] = c; return arr; } public static T[] append(T[] p, T[] cs) { var arr = new T[p.Length + cs.Length]; for (var i = 0; i < p.Length; i++) arr[i] = p[i]; for (var i = 0; i < cs.Length; i++) arr[p.Length + i] = cs[i]; return arr; } static UInt32 _imin_(UInt32 a, UInt32 b) { return a <= b ? a : b; } static UInt32 _imax_(UInt32 a, UInt32 b) { return a >= b ? a : b; } static UInt32 _ibound_(UInt32 lower, UInt32 middle, UInt32 upper) { return _imin_(_imax_(lower, middle), upper); } static Int32 _itimediff(UInt32 later, UInt32 earlier) { return ((Int32)(later - earlier)); } // KCP Segment Definition internal class Segment { internal UInt32 conv = 0; internal UInt32 cmd = 0; internal UInt32 frg = 0; internal UInt32 wnd = 0; internal UInt32 ts = 0; internal UInt32 sn = 0; internal UInt32 una = 0; internal UInt32 resendts = 0; internal UInt32 rto = 0; internal UInt32 fastack = 0; internal UInt32 xmit = 0; internal byte[] data; internal Segment(int size) { this.data = new byte[size]; } // encode a segment into buffer internal int encode(byte[] ptr, int offset) { var offset_ = offset; offset += ikcp_encode32u(ptr, offset, conv); offset += ikcp_encode8u(ptr, offset, (byte)cmd); offset += ikcp_encode8u(ptr, offset, (byte)frg); offset += ikcp_encode16u(ptr, offset, (UInt16)wnd); offset += ikcp_encode32u(ptr, offset, ts); offset += ikcp_encode32u(ptr, offset, sn); offset += ikcp_encode32u(ptr, offset, una); offset += ikcp_encode32u(ptr, offset, (UInt32)data.Length); return offset - offset_; } } // kcp members. UInt32 conv; UInt32 mtu; UInt32 mss; UInt32 state; UInt32 snd_una; UInt32 snd_nxt; UInt32 rcv_nxt; UInt32 ts_recent; UInt32 ts_lastack; UInt32 ssthresh; UInt32 rx_rttval; UInt32 rx_srtt; UInt32 rx_rto; UInt32 rx_minrto; UInt32 snd_wnd; UInt32 rcv_wnd; UInt32 rmt_wnd; UInt32 cwnd; UInt32 probe; UInt32 current; UInt32 interval; UInt32 ts_flush; UInt32 xmit; UInt32 nodelay; UInt32 updated; UInt32 ts_probe; UInt32 probe_wait; UInt32 dead_link; UInt32 incr; Segment[] snd_queue = new Segment[0]; Segment[] rcv_queue = new Segment[0]; Segment[] snd_buf = new Segment[0]; Segment[] rcv_buf = new Segment[0]; UInt32[] acklist = new UInt32[0]; byte[] buffer; Int32 fastresend; Int32 nocwnd; Int32 logmask; // buffer, size Action output; /// /// create a new kcp control object, 'conv' must equal in two endpoint /// from the same connection. /// /// if 0 then use first received conv /// public KCP(UInt32 conv_, Action output_) { conv = conv_; snd_wnd = IKCP_WND_SND; rcv_wnd = IKCP_WND_RCV; rmt_wnd = IKCP_WND_RCV; mtu = IKCP_MTU_DEF; mss = mtu - IKCP_OVERHEAD; rx_rto = IKCP_RTO_DEF; rx_minrto = IKCP_RTO_MIN; interval = IKCP_INTERVAL; ts_flush = IKCP_INTERVAL; ssthresh = IKCP_THRESH_INIT; dead_link = IKCP_DEADLINK; buffer = new byte[(mtu + IKCP_OVERHEAD) * 3]; output = output_; } public void Dispose() { output = null; } public UInt32 GetConv() { return conv; } // check the size of next message in the recv queue public int PeekSize() { if (0 == rcv_queue.Length) return -1; var seq = rcv_queue[0]; if (0 == seq.frg) return seq.data.Length; if (rcv_queue.Length < seq.frg + 1) return -1; int length = 0; foreach (var item in rcv_queue) { length += item.data.Length; if (0 == item.frg) break; } return length; } // user/upper level recv: returns size, returns below zero for EAGAIN public int Recv(byte[] buffer) { if (0 == rcv_queue.Length) return -1; var peekSize = PeekSize(); if (0 > peekSize) return -2; if (peekSize > buffer.Length) return -3; var fast_recover = false; if (rcv_queue.Length >= rcv_wnd) fast_recover = true; // merge fragment. var count = 0; var n = 0; foreach (var seg in rcv_queue) { Array.Copy(seg.data, 0, buffer, n, seg.data.Length); n += seg.data.Length; count++; if (0 == seg.frg) break; } if (0 < count) { rcv_queue = slice(rcv_queue, count, rcv_queue.Length); } // move available data from rcv_buf -> rcv_queue count = 0; foreach (var seg in rcv_buf) { if (seg.sn == rcv_nxt && rcv_queue.Length < rcv_wnd) { rcv_queue = append(rcv_queue, seg); rcv_nxt++; count++; } else { break; } } if (0 < count) rcv_buf = slice(rcv_buf, count, rcv_buf.Length); // fast recover if (rcv_queue.Length < rcv_wnd && fast_recover) { // ready to send back IKCP_CMD_WINS in ikcp_flush // tell remote my window size probe |= IKCP_ASK_TELL; } return n; } // user/upper level send, returns below zero for error public int Send(byte[] buffer, int bufferSize) { if (0 == bufferSize) return -1; var count = 0; if (bufferSize < mss) count = 1; else count = (int)(bufferSize + mss - 1) / (int)mss; if (255 < count) return -2; if (0 == count) count = 1; var offset = 0; for (var i = 0; i < count; i++) { var size = 0; if (bufferSize > mss) size = (int)mss; else size = bufferSize; var seg = new Segment(size); Array.Copy(buffer, offset, seg.data, 0, size); offset += size; seg.frg = (UInt32)(count - i - 1); snd_queue = append(snd_queue, seg); } return 0; } // update ack. void update_ack(Int32 rtt) { if (0 == rx_srtt) { rx_srtt = (UInt32)rtt; rx_rttval = (UInt32)rtt / 2; } else { Int32 delta = (Int32)((UInt32)rtt - rx_srtt); if (0 > delta) delta = -delta; rx_rttval = (3 * rx_rttval + (uint)delta) / 4; rx_srtt = (UInt32)((7 * rx_srtt + rtt) / 8); if (rx_srtt < 1) rx_srtt = 1; } var rto = (int)(rx_srtt + _imax_(1, 4 * rx_rttval)); rx_rto = _ibound_(rx_minrto, (UInt32)rto, IKCP_RTO_MAX); } void shrink_buf() { if (snd_buf.Length > 0) snd_una = snd_buf[0].sn; else snd_una = snd_nxt; } void parse_ack(UInt32 sn) { if (_itimediff(sn, snd_una) < 0 || _itimediff(sn, snd_nxt) >= 0) return; var index = 0; foreach (var seg in snd_buf) { if (sn == seg.sn) { snd_buf = append(slice(snd_buf, 0, index), slice(snd_buf, index + 1, snd_buf.Length)); break; } else { seg.fastack++; } index++; } } void parse_una(UInt32 una) { var count = 0; foreach (var seg in snd_buf) { if (_itimediff(una, seg.sn) > 0) count++; else break; } if (0 < count) snd_buf = slice(snd_buf, count, snd_buf.Length); } void ack_push(UInt32 sn, UInt32 ts) { acklist = append(acklist, new UInt32[2] { sn, ts }); } void ack_get(int p, ref UInt32 sn, ref UInt32 ts) { sn = acklist[p * 2 + 0]; ts = acklist[p * 2 + 1]; } void parse_data(Segment newseg) { var sn = newseg.sn; if (_itimediff(sn, rcv_nxt + rcv_wnd) >= 0 || _itimediff(sn, rcv_nxt) < 0) return; var n = rcv_buf.Length - 1; var after_idx = -1; var repeat = false; for (var i = n; i >= 0; i--) { var seg = rcv_buf[i]; if (seg.sn == sn) { repeat = true; break; } if (_itimediff(sn, seg.sn) > 0) { after_idx = i; break; } } if (!repeat) { if (after_idx == -1) rcv_buf = append(new Segment[1] { newseg }, rcv_buf); else rcv_buf = append(slice(rcv_buf, 0, after_idx + 1), append(new Segment[1] { newseg }, slice(rcv_buf, after_idx + 1, rcv_buf.Length))); } // move available data from rcv_buf -> rcv_queue var count = 0; foreach (var seg in rcv_buf) { if (seg.sn == rcv_nxt && rcv_queue.Length < rcv_wnd) { rcv_queue = append(rcv_queue, seg); rcv_nxt++; count++; } else { break; } } if (0 < count) { rcv_buf = slice(rcv_buf, count, rcv_buf.Length); } } // when you received a low level packet (eg. UDP packet), call it public int Input(byte[] data, int dataLength) { var s_una = snd_una; if (dataLength < IKCP_OVERHEAD) return 0; var offset = 0; while (true) { UInt32 ts = 0; UInt32 sn = 0; UInt32 length = 0; UInt32 una = 0; UInt32 conv_ = 0; UInt16 wnd = 0; byte cmd = 0; byte frg = 0; if (dataLength - offset < IKCP_OVERHEAD) break; offset += ikcp_decode32u(data, offset, ref conv_); if (conv != conv_) { //如果Conv不同,则可能有如下情况 if (conv_ == 0) { //Server收到来自Client的第1个包,Client发出的Conv为0 conv_ = conv; } else if(conv == 0) { //Client收到来自Server的第1个包,Client自己的Conv为0 conv = conv_; } else { return -1; } } offset += ikcp_decode8u(data, offset, ref cmd); offset += ikcp_decode8u(data, offset, ref frg); offset += ikcp_decode16u(data, offset, ref wnd); offset += ikcp_decode32u(data, offset, ref ts); offset += ikcp_decode32u(data, offset, ref sn); offset += ikcp_decode32u(data, offset, ref una); offset += ikcp_decode32u(data, offset, ref length); if (dataLength - offset < length) return -2; switch (cmd) { case IKCP_CMD_PUSH: case IKCP_CMD_ACK: case IKCP_CMD_WASK: case IKCP_CMD_WINS: break; default: return -3; } rmt_wnd = (UInt32)wnd; parse_una(una); shrink_buf(); if (IKCP_CMD_ACK == cmd) { if (_itimediff(current, ts) >= 0) { update_ack(_itimediff(current, ts)); } parse_ack(sn); shrink_buf(); } else if (IKCP_CMD_PUSH == cmd) { if (_itimediff(sn, rcv_nxt + rcv_wnd) < 0) { ack_push(sn, ts); if (_itimediff(sn, rcv_nxt) >= 0) { var seg = new Segment((int)length); seg.conv = conv_; seg.cmd = (UInt32)cmd; seg.frg = (UInt32)frg; seg.wnd = (UInt32)wnd; seg.ts = ts; seg.sn = sn; seg.una = una; if (length > 0) Array.Copy(data, offset, seg.data, 0, length); parse_data(seg); } } } else if (IKCP_CMD_WASK == cmd) { // ready to send back IKCP_CMD_WINS in Ikcp_flush // tell remote my window size probe |= IKCP_ASK_TELL; } else if (IKCP_CMD_WINS == cmd) { // do nothing } else { return -3; } offset += (int)length; } if (_itimediff(snd_una, s_una) > 0) { if (cwnd < rmt_wnd) { var mss_ = mss; if (cwnd < ssthresh) { cwnd++; incr += mss_; } else { if (incr < mss_) { incr = mss_; } incr += (mss_ * mss_) / incr + (mss_ / 16); if ((cwnd + 1) * mss_ <= incr) cwnd++; } if (cwnd > rmt_wnd) { cwnd = rmt_wnd; incr = rmt_wnd * mss_; } } } return 0; } Int32 wnd_unused() { if (rcv_queue.Length < rcv_wnd) return (Int32)(int)rcv_wnd - rcv_queue.Length; return 0; } // flush pending data void flush() { var current_ = current; var buffer_ = buffer; var change = 0; var lost = 0; if (0 == updated) return; var seg = new Segment(0); seg.conv = conv; seg.cmd = IKCP_CMD_ACK; seg.wnd = (UInt32)wnd_unused(); seg.una = rcv_nxt; // flush acknowledges var count = acklist.Length / 2; var offset = 0; for (var i = 0; i < count; i++) { if (offset + IKCP_OVERHEAD > mtu) { output(buffer, offset); //Array.Clear(buffer, 0, offset); offset = 0; } ack_get(i, ref seg.sn, ref seg.ts); offset += seg.encode(buffer, offset); } acklist = new UInt32[0]; // probe window size (if remote window size equals zero) if (0 == rmt_wnd) { if (0 == probe_wait) { probe_wait = IKCP_PROBE_INIT; ts_probe = current + probe_wait; } else { if (_itimediff(current, ts_probe) >= 0) { if (probe_wait < IKCP_PROBE_INIT) probe_wait = IKCP_PROBE_INIT; probe_wait += probe_wait / 2; if (probe_wait > IKCP_PROBE_LIMIT) probe_wait = IKCP_PROBE_LIMIT; ts_probe = current + probe_wait; probe |= IKCP_ASK_SEND; } } } else { ts_probe = 0; probe_wait = 0; } // flush window probing commands if ((probe & IKCP_ASK_SEND) != 0) { seg.cmd = IKCP_CMD_WASK; if (offset + IKCP_OVERHEAD > (int)mtu) { output(buffer, offset); //Array.Clear(buffer, 0, offset); offset = 0; } offset += seg.encode(buffer, offset); } probe = 0; // calculate window size var cwnd_ = _imin_(snd_wnd, rmt_wnd); if (0 == nocwnd) cwnd_ = _imin_(cwnd, cwnd_); count = 0; for (var k = 0; k < snd_queue.Length; k++) { if (_itimediff(snd_nxt, snd_una + cwnd_) >= 0) break; var newseg = snd_queue[k]; newseg.conv = conv; newseg.cmd = IKCP_CMD_PUSH; newseg.wnd = seg.wnd; newseg.ts = current_; newseg.sn = snd_nxt; newseg.una = rcv_nxt; newseg.resendts = current_; newseg.rto = rx_rto; newseg.fastack = 0; newseg.xmit = 0; snd_buf = append(snd_buf, newseg); snd_nxt++; count++; } if (0 < count) { snd_queue = slice(snd_queue, count, snd_queue.Length); } // calculate resent var resent = (UInt32)fastresend; if (fastresend <= 0) resent = 0xffffffff; var rtomin = rx_rto >> 3; if (nodelay != 0) rtomin = 0; // flush data segments foreach (var segment in snd_buf) { var needsend = false; var debug = _itimediff(current_, segment.resendts); if (0 == segment.xmit) { needsend = true; segment.xmit++; segment.rto = rx_rto; segment.resendts = current_ + segment.rto + rtomin; } else if (_itimediff(current_, segment.resendts) >= 0) { needsend = true; segment.xmit++; xmit++; if (0 == nodelay) segment.rto += rx_rto; else segment.rto += rx_rto / 2; segment.resendts = current_ + segment.rto; lost = 1; } else if (segment.fastack >= resent) { needsend = true; segment.xmit++; segment.fastack = 0; segment.resendts = current_ + segment.rto; change++; } if (needsend) { segment.ts = current_; segment.wnd = seg.wnd; segment.una = rcv_nxt; var need = IKCP_OVERHEAD + segment.data.Length; if (offset + need >= mtu) { output(buffer, offset); //Array.Clear(buffer, 0, offset); offset = 0; } offset += segment.encode(buffer, offset); if (segment.data.Length > 0) { Array.Copy(segment.data, 0, buffer, offset, segment.data.Length); offset += segment.data.Length; } if (segment.xmit >= dead_link) { state = 0; } } } // flash remain segments if (offset > 0) { output(buffer, offset); //Array.Clear(buffer, 0, offset); offset = 0; } // update ssthresh if (change != 0) { var inflight = snd_nxt - snd_una; ssthresh = inflight / 2; if (ssthresh < IKCP_THRESH_MIN) ssthresh = IKCP_THRESH_MIN; cwnd = ssthresh + resent; incr = cwnd * mss; } if (lost != 0) { ssthresh = cwnd / 2; if (ssthresh < IKCP_THRESH_MIN) ssthresh = IKCP_THRESH_MIN; cwnd = 1; incr = mss; } if (cwnd < 1) { cwnd = 1; incr = mss; } } // update state (call it repeatedly, every 10ms-100ms), or you can ask // ikcp_check when to call it again (without ikcp_input/_send calling). // 'current' - current timestamp in millisec. public void Update(UInt32 current_) { current = current_; if (0 == updated) { updated = 1; ts_flush = current; } var slap = _itimediff(current, ts_flush); if (slap >= 10000 || slap < -10000) { ts_flush = current; slap = 0; } if (slap >= 0) { ts_flush += interval; if (_itimediff(current, ts_flush) >= 0) ts_flush = current + interval; flush(); } } // Determine when should you invoke ikcp_update: // returns when you should invoke ikcp_update in millisec, if there // is no ikcp_input/_send calling. you can call ikcp_update in that // time, instead of call update repeatly. // Important to reduce unnacessary ikcp_update invoking. use it to // schedule ikcp_update (eg. implementing an epoll-like mechanism, // or optimize ikcp_update when handling massive kcp connections) public UInt32 Check(UInt32 current_) { if (0 == updated) return current_; var ts_flush_ = ts_flush; var tm_flush_ = 0x7fffffff; var tm_packet = 0x7fffffff; var minimal = 0; if (_itimediff(current_, ts_flush_) >= 10000 || _itimediff(current_, ts_flush_) < -10000) { ts_flush_ = current_; } if (_itimediff(current_, ts_flush_) >= 0) return current_; tm_flush_ = (int)_itimediff(ts_flush_, current_); foreach (var seg in snd_buf) { var diff = _itimediff(seg.resendts, current_); if (diff <= 0) return current_; if (diff < tm_packet) tm_packet = (int)diff; } minimal = (int)tm_packet; if (tm_packet >= tm_flush_) minimal = (int)tm_flush_; if (minimal >= interval) minimal = (int)interval; return current_ + (UInt32)minimal; } // change MTU size, default is 1400 public int SetMtu(Int32 mtu_) { if (mtu_ < 50 || mtu_ < (Int32)IKCP_OVERHEAD) return -1; var buffer_ = new byte[(mtu_ + IKCP_OVERHEAD) * 3]; if (null == buffer_) return -2; mtu = (UInt32)mtu_; mss = mtu - IKCP_OVERHEAD; buffer = buffer_; return 0; } public int Interval(Int32 interval_) { if (interval_ > 5000) { interval_ = 5000; } else if (interval_ < 10) { interval_ = 10; } interval = (UInt32)interval_; return 0; } // fastest: ikcp_nodelay(kcp, 1, 20, 2, 1) // nodelay: 0:disable(default), 1:enable // interval: internal update timer interval in millisec, default is 100ms // resend: 0:disable fast resend(default), 1:enable fast resend // nc: 0:normal congestion control(default), 1:disable congestion control public int NoDelay(int nodelay_, int interval_, int resend_, int nc_) { if (nodelay_ > 0) { nodelay = (UInt32)nodelay_; if (nodelay_ != 0) rx_minrto = IKCP_RTO_NDL; else rx_minrto = IKCP_RTO_MIN; } if (interval_ >= 0) { if (interval_ > 5000) { interval_ = 5000; } else if (interval_ < 10) { interval_ = 10; } interval = (UInt32)interval_; } if (resend_ >= 0) fastresend = resend_; if (nc_ >= 0) nocwnd = nc_; return 0; } // set maximum window size: sndwnd=32, rcvwnd=32 by default public int WndSize(int sndwnd, int rcvwnd) { if (sndwnd > 0) snd_wnd = (UInt32)sndwnd; if (rcvwnd > 0) rcv_wnd = (UInt32)rcvwnd; return 0; } // get how many packet is waiting to be sent public int WaitSnd() { return snd_buf.Length + snd_queue.Length; } } } ================================================ FILE: SGFCore/Network/Core/KCP/switch_queue.cs ================================================ using System; using System.Collections; namespace SGF.Network.Core { public class Utility { public static void Swap(ref QT t1, ref QT t2) { QT temp = t1; t1 = t2; t2 = temp; } } public class SwitchQueue where T : class { private Queue mConsumeQueue; private Queue mProduceQueue; public SwitchQueue() { mConsumeQueue = new Queue(16); mProduceQueue = new Queue(16); } public SwitchQueue(int capcity) { mConsumeQueue = new Queue(capcity); mProduceQueue = new Queue(capcity); } // producer public void Push(T obj) { lock (mProduceQueue) { mProduceQueue.Enqueue(obj); } } // consumer. public T Pop() { return (T)mConsumeQueue.Dequeue(); } public bool Empty() { return 0 == mConsumeQueue.Count; } public void Switch() { lock (mProduceQueue) { Utility.Swap(ref mConsumeQueue, ref mProduceQueue); } } public void Clear() { lock (mProduceQueue) { mConsumeQueue.Clear(); mProduceQueue.Clear(); } } } } ================================================ FILE: SGFCore/Network/Core/NetBuffer.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 封装了对网络字节流的操作 * Encapsulates operations on network byte streams * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Text; using SGF.Codec; namespace SGF.Network.Core { public class NetBuffer { public static byte[] ReverseOrder(byte[] dt) { if (!BitConverter.IsLittleEndian) { return dt; } int count = dt.Length; if (count > 1) { int half = count / 2; int maxIndex = count - 1; for (int i = 0; i < half; i++) { byte temp = dt[i]; int swapIndex = maxIndex - i; dt[i] = dt[swapIndex]; dt[swapIndex] = temp; } } return dt; } protected int m_pos = 0; protected int m_len = 0; protected int m_capacity = 0; protected byte[] m_buff = null; /// /// 临时字节长度 /// protected byte[] m_16b = new byte[2]; protected byte[] m_32b = new byte[4]; protected byte[] m_64b = new byte[8]; public NetBuffer(int capacity) { this.m_capacity = capacity; this.m_buff = new byte[capacity]; this.m_pos = 0; this.m_len = 0; } public NetBuffer(byte[] buff = null) { this.m_capacity = 0; this.m_pos = 0; this.m_len = 0; this.m_buff = buff; if (buff != null) { this.m_capacity = buff.Length; } } public NetBuffer Attach(byte[] buff, int len) { if (buff == null) { throw new Exception("NetBuffer Attach A Null Buffer!"); } this.m_pos = 0; this.m_buff = buff; this.m_len = System.Math.Min(len, buff.Length); this.m_capacity = buff.Length; return this; } public void Clear() { m_len = 0; m_pos = 0; } public void AdjustCapacity(int newCapacity) { if (newCapacity < m_len) { m_len = newCapacity; if (m_pos > m_len) { m_pos = m_len; } } byte[] newBuff = new byte[newCapacity]; Buffer.BlockCopy(m_buff, 0, newBuff, 0, m_len); m_capacity = newCapacity; m_buff = newBuff; } public int Capacity { get { return m_capacity; } } public int Position { get { return m_pos; } set { m_pos = value; } } public int Length { get { return m_len; } } public int BytesAvailable { get { return (m_len - m_pos); } } public byte[] GetBytes() { return m_buff; } public void SetPositionToLength() { m_pos = m_len; } public string ToHexString() { return SGFEncoding.BytesToHex(m_buff, m_len); } public override string ToString() { return ToHexString(); } /// /// 去掉已经读完的字节 /// 装POSITION设置成0 /// public void Arrangement(int pos = -1) { pos = pos == -1 ? m_pos : pos; if (pos > m_len) { pos = m_len; } if (pos < 0) { pos = 0; } int size = 0; if (pos < m_len) { size = m_len - pos; } Buffer.BlockCopy(m_buff, pos, m_buff, 0, size); m_len = size; m_pos = 0; } /// /// 将位置设置到最大 /// private int UpdateLenAndGetWritePos(int writePos, int writeLen) { if (writePos == -1) { if (m_len + writeLen > m_capacity) { throw new Exception("SGFBuffer out of capacity."); } writePos = m_len; m_len = writePos + writeLen; } else { if (writePos + writeLen > m_capacity) { throw new Exception("SGFBuffer out of capacity."); } if (writePos + writeLen > m_len) { m_len = writePos + writeLen; } } return writePos; } /// /// 将Byte[]写入Buffer的末尾 /// 不移动游标,返回长度 /// public int AddBytes(byte[] src, int srcOffset = 0, int count = 0) { if (count <= 0) { count = src.Length - srcOffset; } if (m_len + count > m_capacity) { throw new Exception("SGFBuffer(" + m_len + "+" + count + ") Out of Capacity(" + m_capacity + ")."); } Buffer.BlockCopy(src, srcOffset, m_buff, m_len, count); m_len += count; //m_pos += count; //不移动游标 return m_len; } public int AddBuffer(NetBuffer src) { return AddBytes(src.m_buff, 0, src.m_len); } /// /// 把src对象的数组copy到本对象,从dstOffect的地方开始 /// 不移动游标,返回长度 /// public int CopyWith(NetBuffer src, int dstOffset = 0, bool bResetLen = false) { return CopyWith(src, 0, dstOffset, bResetLen); } /// /// 把src对象的数组从srcOffset开始copy到本对象从dstOffect的地方开始 /// 不移动游标,返回长度 /// public int CopyWith(NetBuffer src, int srcOffset, int dstOffset = 0, bool bResetLen = false) { Buffer.BlockCopy(src.m_buff, srcOffset, m_buff, dstOffset, src.m_len); int newLen = dstOffset + src.m_len - srcOffset; if (newLen > m_len || bResetLen) { m_len = newLen; } return m_len; } /// /// 从指定Pos增加指定Len /// public void AddLength(int len, int writePos = -1) { UpdateLenAndGetWritePos(writePos, len); if (writePos == 0) { m_len = len; } } //===================================================== //写入数据,如果WritePos是-1,则写在Buffer末尾。 //否则写在WritePos的位置 //由于很多时候不是按顺序写的,所以写入时,不改变内部的Pos。 //但是会返回当前写入后的新Pos值 public int WriteByte(byte value, int writePos = -1) { int pos = UpdateLenAndGetWritePos(writePos, 1); m_buff[pos] = value; return pos + 1; } public int WriteShort(short value, int writePos = -1) { int pos = UpdateLenAndGetWritePos(writePos, 2); m_buff[pos + 0] = (byte)(value >> 8 & 0xFF); m_buff[pos + 1] = (byte)(value >> 0 & 0xFF); return pos + 2; } public int WriteInt(int value, int writePos = -1) { int pos = UpdateLenAndGetWritePos(writePos, 4); m_buff[pos + 0] = (byte)(value >> 24 & 0xFF); m_buff[pos + 1] = (byte)(value >> 16 & 0xFF); m_buff[pos + 2] = (byte)(value >> 08 & 0xFF); m_buff[pos + 3] = (byte)(value >> 00 & 0xFF); return pos + 4; } public int WriteUShort(ushort value, int writePos = -1) { return WriteShort((short)value, writePos); } public int WriteUInt(uint value, int writePos = -1) { return WriteInt((int)value, writePos); } public int WriteBytes(byte[] src, int srcOffset, int count, int writePos = -1) { int pos = UpdateLenAndGetWritePos(writePos, count); Buffer.BlockCopy(src, srcOffset, m_buff, pos, count); return pos + count; } public int WriteBytes(byte[] value, int writePos = -1) { return WriteBytes(value, 0, value.Length, writePos); } public int WriteDouble(double value, int writePos = -1) { byte[] bytes = BitConverter.GetBytes(value); return WriteBytes(NetBuffer.ReverseOrder(bytes), writePos); } public int WriteFloat(float value, int writePos = -1) { byte[] bytes = BitConverter.GetBytes(value); return WriteBytes(NetBuffer.ReverseOrder(bytes), writePos); } public void WriteLong(long l, int writePos = -1) { byte[] bytes = BitConverter.GetBytes(l); this.WriteBytes(NetBuffer.ReverseOrder(bytes), writePos); } public void WriteULong(ulong l, int writePos = -1) { byte[] bytes = BitConverter.GetBytes(l); this.WriteBytes(NetBuffer.ReverseOrder(bytes), writePos); } public int WriteUTF8(string value, int writePos = -1) { byte[] tmp = Encoding.UTF8.GetBytes(value); int nextPos = WriteInt(tmp.Length, writePos); return WriteBytes(tmp, nextPos); } public int Skip(int count) { m_pos += count; return m_pos; } //============================================================= ///读取数据 /// public void ReadBytes(byte[] dst, int dstOffset, int count) { Buffer.BlockCopy(this.m_buff, this.m_pos, dst, dstOffset, count); this.m_pos += count; } public byte[] ReadBytes(int count) { byte[] dst = new byte[count]; ReadBytes(dst, 0, count); return dst; } public bool ReadBool() { return (this.m_buff[this.m_pos++] == 1); } public byte ReadByte() { return this.m_buff[this.m_pos++]; } public double ReadDouble() { ReadBytes(m_64b, 0, 8); return BitConverter.ToDouble(NetBuffer.ReverseOrder(m_64b), 0); } public float ReadFloat() { ReadBytes(m_32b, 0, 4); return BitConverter.ToSingle(NetBuffer.ReverseOrder(m_32b), 0); } public int ReadInt() { ReadBytes(m_32b, 0, 4); return BitConverter.ToInt32(NetBuffer.ReverseOrder(m_32b), 0); } public uint ReadUInt() { ReadBytes(m_32b, 0, 4); return BitConverter.ToUInt32(NetBuffer.ReverseOrder(m_32b), 0); } public long ReadLong() { ReadBytes(m_64b, 0, 8); return BitConverter.ToInt64(NetBuffer.ReverseOrder(m_64b), 0); } public ulong ReadULong() { ReadBytes(m_64b, 0, 8); return BitConverter.ToUInt64(NetBuffer.ReverseOrder(m_64b), 0); } public short ReadShort() { ReadBytes(m_16b, 0, 2); return BitConverter.ToInt16(NetBuffer.ReverseOrder(m_16b), 0); } public ushort ReadUShort() { ReadBytes(m_16b, 0, 2); return BitConverter.ToUInt16(NetBuffer.ReverseOrder(m_16b), 0); } public string ReadUTF() { int count = this.ReadInt(); string str = Encoding.UTF8.GetString(this.m_buff, this.m_pos, count); this.m_pos += count; return str; } } /// /// 字节读出 /// public class NetBufferReader : NetBuffer { static public NetBufferReader DEFAULT = new NetBufferReader(); public NetBufferReader(byte[] buff = null) : base(buff) { if (buff != null) { m_len = buff.Length; } } } /// /// 字节写入... /// public class NetBufferWriter : NetBuffer { static public NetBufferWriter DEFAULT = new NetBufferWriter(); public NetBufferWriter(byte[] buff = null) : base(buff) { } } } ================================================ FILE: SGFCore/Network/Core/NetErrorCode.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 网络模块 * Network * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ namespace SGF.Network.Core { public enum NetErrorCode { UnkownError = -1, NoError = 0, SocketError, Timeout, Disconnected, SessionExpire, DeserializeError, ReconnectFailed //不能超过SocketError的枚举值 } } ================================================ FILE: SGFCore/Network/Core/RPCLite/RPCManagerBase.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 实现基于C#反射机制的RPC基础功能 * 它需要结合具体的通讯模块使用 * Implement RPC basic functions based on C# reflection mechanism  * It needs to be used in conjunction with specific communication modules * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using SGF.Utils; using System; using System.Collections.Generic; using System.Reflection; using System.Text; namespace SGF.Network.Core.RPCLite { public class RPCRequestAttribute : Attribute { } public class RPCResponseAttribute : Attribute { } public class RPCNotifyAttribute : Attribute { } public class RPCMethodHelper { public object listener; public MethodInfo method; } public class RPCManagerBase { protected List m_listListener; protected DictionarySafe m_mapMethodHelper; public void Init() { m_listListener = new List(); m_mapMethodHelper = new DictionarySafe(); } public void Clean() { m_listListener.Clear(); foreach (var pair in m_mapMethodHelper) { pair.Value.listener = null; pair.Value.method = null; } m_mapMethodHelper.Clear(); } public void Dump() { StringBuilder sb = new StringBuilder(); foreach (var pair in m_mapMethodHelper) { RPCMethodHelper helper = pair.Value; sb.AppendFormat("\t\n", pair.Key, helper.method.DeclaringType.Name, helper.method.Name); } Debuger.LogWarning("\nRPC Cached Methods ({0}):\n{1}", m_mapMethodHelper.Count, sb); } public void RegisterListener(object listener) { if (!m_listListener.Contains(listener)) { Debuger.Log("{0}", listener.GetType().Name); m_listListener.Add(listener); } } public void UnRegisterListener(object listener) { if (m_listListener.Contains(listener)) { Debuger.Log("{0}", listener.GetType().Name); m_listListener.Remove(listener); } List listMethods = new List(); foreach (var helper in m_mapMethodHelper) { if (helper.Value.listener == listener) { listMethods.Add(helper.Key); } } for (int i = 0; i < listMethods.Count; i++) { m_mapMethodHelper.Remove(listMethods[i]); } } public RPCMethodHelper GetMethodHelper(string name) { var helper = m_mapMethodHelper[name]; if (helper == null) { MethodInfo mi = null; object listener = null; for (int i = 0; i < m_listListener.Count; i++) { listener = m_listListener[i]; mi = listener.GetType().GetMethod(name, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public); if (mi != null) { break; } } if (mi != null) { helper = new RPCMethodHelper(); helper.listener = listener; helper.method = mi; m_mapMethodHelper.Add(name, helper); } } return helper; } } } ================================================ FILE: SGFCore/Network/Core/RPCLite/RPCMessage.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 实现基于C#反射机制的RPC基础功能 * 它需要结合具体的通讯模块使用 * Implement RPC basic functions based on C# reflection mechanism  * It needs to be used in conjunction with specific communication modules * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Text; using ProtoBuf; using SGF.Codec; namespace SGF.Network.Core.RPCLite { [ProtoContract] public class RPCMessage { [ProtoMember(1)] public string name; [ProtoMember(2)] public List raw_args = new List(); public object[] args { get { var list = new List(); for (int i = 0; i < raw_args.Count; i++) { list.Add(raw_args[i].value); } return list.ToArray(); } set { raw_args = new List(); object[] list = value; for (int i = 0; i < list.Length; i++) { var raw_arg = new RPCRawArg(); raw_arg.value = list[i]; raw_args.Add(raw_arg); } } } } [ProtoContract] public class RPCRawArg { [ProtoMember(1)] public RPCArgType type; [ProtoMember(2)] public byte[] raw_value; public object value { get { if (raw_value == null || raw_value.Length == 0) { return null; } NetBufferReader reader = new NetBufferReader(raw_value); switch (type) { case RPCArgType.Int: return reader.ReadInt(); case RPCArgType.UInt: return reader.ReadUInt(); case RPCArgType.Long: return reader.ReadLong(); case RPCArgType.ULong: return reader.ReadULong(); case RPCArgType.Short: return reader.ReadShort(); case RPCArgType.UShort: return reader.ReadUShort(); case RPCArgType.Double: return reader.ReadDouble(); case RPCArgType.Float: return reader.ReadFloat(); case RPCArgType.String: return Encoding.UTF8.GetString(raw_value); case RPCArgType.Byte: return reader.ReadByte(); case RPCArgType.Bool: return reader.ReadByte() != 0; case RPCArgType.ByteArray: return raw_value; case RPCArgType.PBObject: return raw_value;//由于数据层是不知道具体类型,由反射层去反序列化 default: return raw_value; } } set { NetBuffer writer; object v = value; if (v is int) { type = RPCArgType.Int; raw_value = BitConverter.GetBytes((int) v); NetBuffer.ReverseOrder(raw_value); } else if (v is uint) { type = RPCArgType.UInt; raw_value = BitConverter.GetBytes((uint)v); NetBuffer.ReverseOrder(raw_value); } else if (v is long) { type = RPCArgType.Long; raw_value = BitConverter.GetBytes((long)v); NetBuffer.ReverseOrder(raw_value); } else if (v is ulong) { type = RPCArgType.ULong; raw_value = BitConverter.GetBytes((ulong)v); NetBuffer.ReverseOrder(raw_value); } else if (v is short) { type = RPCArgType.Short; raw_value = BitConverter.GetBytes((short)v); NetBuffer.ReverseOrder(raw_value); } else if (v is ushort) { type = RPCArgType.UShort; raw_value = BitConverter.GetBytes((ushort)v); NetBuffer.ReverseOrder(raw_value); } else if (v is double) { type = RPCArgType.Double; raw_value = BitConverter.GetBytes((double)v); } else if (v is float) { type = RPCArgType.Float; raw_value = BitConverter.GetBytes((float)v); NetBuffer.ReverseOrder(raw_value); } else if (v is string) { type = RPCArgType.String; raw_value = Encoding.UTF8.GetBytes((string)v); } else if (v is byte) { type = RPCArgType.Byte; raw_value = new[] { (byte)v }; } else if (v is bool) { type = RPCArgType.Bool; raw_value = new[] { (bool)v ? (byte)1 : (byte)0 }; } else if (v is byte[]) { type = RPCArgType.ByteArray; raw_value = new byte[((byte[])v).Length]; Buffer.BlockCopy((byte[])v, 0, raw_value, 0, raw_value.Length); } else { var bytes = PBSerializer.NSerialize(v); if (bytes != null) { type = RPCArgType.PBObject; raw_value = new byte[bytes.Length]; Buffer.BlockCopy(bytes, 0, raw_value, 0, raw_value.Length); } else { type = RPCArgType.Unkown; Debuger.LogError("该参数无法序列化!value:{0}", v); } } } } } public enum RPCArgType { Unkown = 0, Int = 1, UInt = 2, Long = 3, ULong = 4, Short = 5, UShort = 6, Double = 8, Float = 9, String = 10, Byte = 11, Bool = 12, ByteArray = 31, PBObject = 32 } } ================================================ FILE: SGFCore/Network/Core/SocketAsyncEventArgsPool.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System.Collections.Generic; using System.Net.Sockets; namespace SGF.Network.Core { public class SocketAsyncEventArgsPool { private readonly int m_poolSize; private readonly int m_packedBufferSize; private readonly Stack m_pool = new Stack(); public SocketAsyncEventArgsPool(int packetBufferSize, int poolSize) { this.m_packedBufferSize = packetBufferSize; this.m_poolSize = poolSize; } public SocketAsyncEventArgs Acquire() { SocketAsyncEventArgs e = null; lock (m_pool) { if (m_pool.Count > 0) { return m_pool.Pop(); } } e = new SocketAsyncEventArgs(); e.SetBuffer(new byte[this.m_packedBufferSize], 0, this.m_packedBufferSize); return e; } public void Release(SocketAsyncEventArgs e) { lock (m_pool) { if (this.m_pool.Count < m_poolSize) { this.m_pool.Push(e); return; } } e.Dispose(); } public void Clear() { lock (m_pool) { SocketAsyncEventArgs e = null; while (m_pool.Count > 0) { e = m_pool.Pop(); e.Dispose(); } } } } } ================================================ FILE: SGFCore/Network/Core/UdpSocket.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 封装了以Udp模式工作的Socket * Encapsulates Sockets working in Udp mode * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Net; using System.Net.Sockets; namespace SGF.Network.Core { public class UdpSocket { //=========================================================== public static string LOG_TAG = "UdpSocket"; private bool m_IsActive; private Socket m_SystemSocket; private AddressFamily m_AddrFamily; private bool m_IsBroadcast; private bool m_EnableBlockOnRecv = false;//是否允许在接收数据时阻塞 //=========================================================== #region 构造与析构 public UdpSocket(AddressFamily family, bool enableBlockOnRecv = false) { m_EnableBlockOnRecv = enableBlockOnRecv; m_AddrFamily = family; m_SystemSocket = new Socket(m_AddrFamily, SocketType.Dgram, ProtocolType.Udp); } public AddressFamily AddressFamily { get { return m_AddrFamily; } } public void Dispose() { Close(); } public void Close() { if (m_SystemSocket != null) { try { m_SystemSocket.Shutdown(SocketShutdown.Both); } catch (Exception e) { Debuger.LogWarning(LOG_TAG, "Close() " + e.Message + e.StackTrace); } m_SystemSocket.Close(); m_SystemSocket = null; } m_IsActive = false; GC.SuppressFinalize(this); } public string SelfIP { get { return IPUtils.SelfIP; } } public int SelfPort { get { IPEndPoint ipep = m_SystemSocket.LocalEndPoint as IPEndPoint; return ipep.Port; } } public Socket SystemSocket { get { return m_SystemSocket; } } public int Available { get { return m_SystemSocket.Available; } } #endregion //------------------------------------------------------------ #region 绑定端口函数 public int Bind(int port = 0) { Debuger.Log(LOG_TAG, "Bind() port = " + port); if (m_SystemSocket == null) { return 0; } //如果Bind的端口为0,则会随机分配一个端口 IPEndPoint ipep = IPUtils.GetIPEndPointAny(m_AddrFamily, port); m_SystemSocket.Bind(ipep); m_IsActive = true; return SelfPort; } #endregion //------------------------------------------------------------ #region ReceiveFrom和SendTo函数 public int ReceiveFrom(byte[] buffer, int maxsize, ref IPEndPoint remoteEP) { int cnt = 0; EndPoint ip = null; if (!m_EnableBlockOnRecv) { if (m_SystemSocket.Available <= 0) { return 0; } } if (m_AddrFamily == AddressFamily.InterNetwork) { //如果是IPv4环境,则(与Android的处理一样) ip = IPUtils.GetIPEndPointAny(AddressFamily.InterNetwork, 0); cnt = m_SystemSocket.ReceiveFrom(buffer, maxsize, SocketFlags.None, ref ip); if (cnt > 0 && remoteEP != null && !remoteEP.Equals(ip)) { Debuger.LogWarning(LOG_TAG, "ReceiveFrom() 收到一个自来陌生IP:Port(" + ip + ")的数据包!"); return 0; } } else { //如果是IPv6环境,则: ip = remoteEP; cnt = m_SystemSocket.ReceiveFrom(buffer, maxsize, SocketFlags.None, ref ip); } remoteEP = ip as IPEndPoint; return cnt; } public int SendTo(byte[] buffer, int size, IPEndPoint remoteEP) { int cnt = 0; //如果无法使用LocalSocket再使用SystemSocket if (cnt == 0) { cnt = m_SystemSocket.SendTo(buffer, 0, size, SocketFlags.None, remoteEP); } return cnt; } #endregion } } ================================================ FILE: SGFCore/Network/Debuger/NetDebugFile.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 提供网络相关的调试功能 * Provides network-related debugging features * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using SGF.Codec; using SGF.Network.protocol; using SGF.Utils; namespace SGF.Network { public class NetDebugFile { private NetDebugFileData m_content; public NetDebugFileData Content { get { return m_content; } } private DictionarySafe> m_mapAllSampleList; private List m_listAllSampleName; public List ListAllSampleName { get { return m_listAllSampleName; } } public NetDebugFile() { m_content = new NetDebugFileData(); m_mapAllSampleList = new DictionarySafe>(); m_listAllSampleName = new List(); } public List GetSampleList(string name) { return m_mapAllSampleList[name]; } public bool Save(string dirname, string filename) { Debuger.Log(""); if (string.IsNullOrEmpty(filename)) { return false; } string errinfo = ""; byte[] buffer = PBSerializer.NSerialize(m_content); return FileUtils.SaveFile(dirname + filename, buffer) > 0; } public bool Open(string dirname, string filename) { string fullpath = filename; if (!PathUtils.IsFullPath(filename)) { fullpath = dirname + "/" + filename; } return Open(fullpath); } public bool Open(string fullpath) { Debuger.Log("fullpath = " + fullpath); Byte[] bytes = FileUtils.ReadFile(fullpath); if (bytes != null && bytes.Length > 0) { m_content = PBSerializer.NDeserialize(bytes); return ParserFile(); } else { Debuger.LogError("File Is Not Exist, Or Open Wrong!"); return false; } return true; } private bool ParserFile() { m_mapAllSampleList.Clear(); m_listAllSampleName.Clear(); if (m_content == null) { return false; } List listAll = m_content.profiler_samples; for (int i = 0; i < listAll.Count; i++) { NetSampleItem item = listAll[i]; List list = m_mapAllSampleList[item.name]; if (list == null) { list = new List(); m_mapAllSampleList.Add(item.name, list); m_listAllSampleName.Add(item.name); } list.Add(item); } return true; } } } ================================================ FILE: SGFCore/Network/Debuger/NetDebuger.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 提供网络相关的调试功能 * Provides network-related debugging features * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using SGF.MathLite; using SGF.Network.protocol; namespace SGF.Network { public static class NetDebuger { public const string LOG_TAG = "NetDebuger"; public static string DbgFileName { get; set; } public static string DbgFileDir { get; set; } //=========================================================== public static bool EnableLog = false; public static bool EnableProfiler = false; //=========================================================== //弱网络测试 public static bool EnableWeakNet = false; public static float PacketLossRate = 0;//丢包率 public static float JitterRate = 0;//抖动率 public static int JitterDelayMin = 0;//MS public static int JitterDelayMax = 0; //=========================================================== //========================================================================= //========================================================================= #region Profiler采样 private static List m_ListNetSamples = new List(); public static List SampleList { get { return m_ListNetSamples; } } public static void ClearSample() { m_ListNetSamples.Clear(); } public static void AddSample(string tag, string name, int data1 = 0, int data2 = 0, int data3 = 0) { if (EnableProfiler) { NetSampleItem item = new NetSampleItem(); item.name = tag + ":" + name; item.time = DateTime.Now.Ticks; item.data1 = data1; item.data2 = data2; item.data3 = data3; m_ListNetSamples.Add(item); } } #endregion //========================================================================= //弱网络测试 #region 弱网络测试 public static int GetJitterDelay() { if (IsNetJitter()) { return SGFRandom.Default.Range(JitterDelayMin, JitterDelayMax); } return 0; } public static bool IsNetJitter() { return EnableWeakNet && SGFRandom.Default.Rnd() < JitterRate; } public static bool IsPacketLoss() { return EnableWeakNet && SGFRandom.Default.Rnd() < PacketLossRate; } public static void WeakNetSimulate(object target, byte[] buffer, int size, Action handler) { } public static void WeakNetCancel(object target) { } private static void OnDelayInvoke(object[] args) { Action handler = (Action)args[0]; if (handler != null) { handler((byte[])args[1], (int)args[2]); } } #endregion } } ================================================ FILE: SGFCore/Network/Debuger/net_debuger.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ // Generated from: fsp_debuger.proto namespace SGF.Network.protocol { [global::System.Serializable, global::ProtoBuf.ProtoContract(Name=@"NetSampleItem")] public partial class NetSampleItem : global::ProtoBuf.IExtensible { public NetSampleItem() { } private string _name = ""; [global::ProtoBuf.ProtoMember(1, IsRequired = false, Name=@"name", DataFormat = global::ProtoBuf.DataFormat.Default)] [global::System.ComponentModel.DefaultValue("")] public string name { get { return _name; } set { _name = value; } } private long _time = default(long); [global::ProtoBuf.ProtoMember(2, IsRequired = false, Name=@"time", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)] [global::System.ComponentModel.DefaultValue(default(long))] public long time { get { return _time; } set { _time = value; } } private int _data1 = default(int); [global::ProtoBuf.ProtoMember(3, IsRequired = false, Name=@"data1", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)] [global::System.ComponentModel.DefaultValue(default(int))] public int data1 { get { return _data1; } set { _data1 = value; } } private int _data2 = default(int); [global::ProtoBuf.ProtoMember(4, IsRequired = false, Name=@"data2", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)] [global::System.ComponentModel.DefaultValue(default(int))] public int data2 { get { return _data2; } set { _data2 = value; } } private int _data3 = default(int); [global::ProtoBuf.ProtoMember(5, IsRequired = false, Name=@"data3", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)] [global::System.ComponentModel.DefaultValue(default(int))] public int data3 { get { return _data3; } set { _data3 = value; } } private global::ProtoBuf.IExtension extensionObject; global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) { return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); } } [global::System.Serializable, global::ProtoBuf.ProtoContract(Name = @"NetDebugFileData")] public partial class NetDebugFileData : global::ProtoBuf.IExtensible { public NetDebugFileData() { } private readonly global::System.Collections.Generic.List _profiler_samples = new global::System.Collections.Generic.List(); [global::ProtoBuf.ProtoMember(1, Name=@"profiler_samples", DataFormat = global::ProtoBuf.DataFormat.Default)] public global::System.Collections.Generic.List profiler_samples { get { return _profiler_samples; } } private global::ProtoBuf.IExtension extensionObject; global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) { return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); } } } ================================================ FILE: SGFCore/Network/FSPLite/Client/FSPClient.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 帧同步模块 * Frame synchronization module * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Threading; using SGF.Codec; using SGF.Extension; using SGF.Network.Core; using SGF.Time; using SGF.Utils; namespace SGF.Network.FSPLite.Client { public class FSPClient { private bool m_IsRunning = false; //基础通讯部分 private string m_ip; private int m_port; private uint m_sid; private Socket m_SystemSocket; private Thread m_ThreadRecv; private IPEndPoint m_RemoteEndPoint; private bool m_WaitForReconnect = false; private uint m_lastRecvTimestamp = 0; //KCP部分 private KCP m_Kcp; private SwitchQueue m_RecvBufQueue = new SwitchQueue(128); private bool m_NeedKcpUpdateFlag = false; private uint m_NextKcpUpdateTime = 0; private int m_authId; //接收逻辑 private Action m_RecvListener; private byte[] m_RecvBufferTemp = new byte[4096]; //发送逻辑 private FSPDataC2S m_TempSendData = new FSPDataC2S(); private byte[] m_SendBufferTemp = new byte[4096]; //------------------------------------------------------------ #region 构造相关 public void Init(uint sid) { Debuger.Log("sid:{0}", sid); m_sid = sid; m_TempSendData.sid = sid; m_TempSendData.msgs.Add(new FSPMessage()); m_Kcp = new KCP(m_sid, HandleKcpSend); m_Kcp.NoDelay(1, 10, 2, 1); m_Kcp.WndSize(128, 128); } public void Clean() { Debuger.Log(); if (m_Kcp != null) { m_Kcp.Dispose(); m_Kcp = null; } m_RecvListener = null; Close(); } #endregion //------------------------------------------------------------ #region 设置参数 public void SetFSPAuthInfo(int authId) { Debuger.Log(authId); m_authId = authId; } public void SetFSPListener(Action listener) { Debuger.Log(); m_RecvListener = listener; } public void VerifyAuth() { Debuger.Log(); SendFSP(0, FSPBasicCmd.AUTH, m_authId); } #endregion //------------------------------------------------------------ #region 连接相关逻辑 public bool IsRunning { get { return m_IsRunning; } } public bool Connect(string ip, int port) { if (m_SystemSocket != null) { Debuger.LogError("无法建立连接,需要先关闭上一次连接!"); return false; } Debuger.Log("建立基础连接, host = {0}, port = {1}", ip, port); m_ip = ip; m_port = port; m_lastRecvTimestamp = (uint)TimeUtils.GetTotalMillisecondsSince1970(); try { m_RemoteEndPoint = IPUtils.GetHostEndPoint(m_ip, m_port); if (m_RemoteEndPoint == null) { Debuger.LogError("无法将Host解析为IP!"); Close(); return false; } Debuger.Log("HostEndPoint = {0}", m_RemoteEndPoint.ToString()); //创建Socket Debuger.Log("创建Socket, AddressFamily = {0}", m_RemoteEndPoint.AddressFamily); m_SystemSocket = new Socket(m_RemoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp); m_SystemSocket.Bind(IPUtils.GetIPEndPointAny(AddressFamily.InterNetwork, 0)); m_IsRunning = true; m_ThreadRecv = new Thread(Thread_Recv) { IsBackground = true }; m_ThreadRecv.Start(); } catch (Exception e) { Debuger.LogError(e.Message + e.StackTrace); Close(); return false; } return true; } private void Close() { Debuger.Log(); m_IsRunning = false; if (m_ThreadRecv != null) { m_ThreadRecv.Interrupt(); m_ThreadRecv = null; } if (m_SystemSocket != null) { try { m_SystemSocket.Shutdown(SocketShutdown.Both); } catch (Exception e) { Debuger.LogWarning(e.Message + e.StackTrace); } m_SystemSocket.Close(); m_SystemSocket = null; } } private void Reconnect() { m_WaitForReconnect = false; Close(); Connect(m_ip, m_port); VerifyAuth(); } #endregion //------------------------------------------------------------ private void Thread_Recv() { while (m_IsRunning) { try { DoReceiveInThread(); } catch (SocketException se) { Debuger.LogWarning("SocketErrorCode:{0}, {1}", se.SocketErrorCode, se.Message); Thread.Sleep(1); } catch (Exception e) { Debuger.LogWarning(e.Message + "\n" + e.StackTrace); Thread.Sleep(1); } } } private void DoReceiveInThread() { EndPoint remotePoint = IPUtils.GetIPEndPointAny(AddressFamily.InterNetwork, 0); int cnt = m_SystemSocket.ReceiveFrom(m_RecvBufferTemp, m_RecvBufferTemp.Length, SocketFlags.None, ref remotePoint); if (cnt > 0) { if (!m_RemoteEndPoint.Equals(remotePoint)) { Debuger.LogError("收到非目标服务器的数据!"); return; } byte[] dst = new byte[cnt]; Buffer.BlockCopy(m_RecvBufferTemp, 0, dst, 0, cnt); m_RecvBufQueue.Push(dst); } } private void DoReceiveInMain() { m_RecvBufQueue.Switch(); while (!m_RecvBufQueue.Empty()) { var recvBufferRaw = m_RecvBufQueue.Pop(); int ret = m_Kcp.Input(recvBufferRaw, recvBufferRaw.Length); //收到的不是一个正确的KCP包 if (ret < 0) { Debuger.LogError("收到不正确的KCP包, Ret:{0}", ret); return; } m_NeedKcpUpdateFlag = true; for (int size = m_Kcp.PeekSize(); size > 0; size = m_Kcp.PeekSize()) { var recvBuffer = new byte[size]; if (m_Kcp.Recv(recvBuffer) > 0) { m_lastRecvTimestamp = (uint)TimeUtils.GetTotalMillisecondsSince1970(); var data = PBSerializer.NDeserialize(recvBuffer); if (m_RecvListener != null) { for (int i = 0; i < data.frames.Count; i++) { m_RecvListener(data.frames[i]); } } } } } } //------------------------------------------------------------ #region 发送相关逻辑 private void HandleKcpSend(byte[] buffer, int size) { m_SystemSocket.SendTo(buffer, 0, size, SocketFlags.None, m_RemoteEndPoint); } public bool SendFSP(int clientFrameId, int cmd, int arg) { return SendFSP(clientFrameId, cmd, new int[] {arg}); } public bool SendFSP(int clientFrameId, int cmd, int[] args) { Debuger.Log("clientFrameId:{0}, cmd:{1}, args:{2}", clientFrameId, cmd, args.ToListString()); if (m_IsRunning) { FSPMessage msg = m_TempSendData.msgs[0]; msg.cmd = cmd; msg.clientFrameId = clientFrameId; msg.args = args; m_TempSendData.msgs.Clear(); m_TempSendData.msgs.Add(msg); int len = PBSerializer.NSerialize(m_TempSendData, m_SendBufferTemp); m_Kcp.Send(m_SendBufferTemp, len); return len > 0; } return false; } #endregion //------------------------------------------------------------ private void CheckTimeout() { uint current = (uint)TimeUtils.GetTotalMillisecondsSince1970(); var dt = current - m_lastRecvTimestamp; if (dt > 5000) { m_WaitForReconnect = true; } } public void Tick() { if (!m_IsRunning) { return; } DoReceiveInMain(); uint current = (uint)TimeUtils.GetTotalMillisecondsSince1970(); if (m_NeedKcpUpdateFlag || current >= m_NextKcpUpdateTime) { if (m_Kcp != null) { m_Kcp.Update(current); m_NextKcpUpdateTime = m_Kcp.Check(current); m_NeedKcpUpdateFlag = false; } } if (m_WaitForReconnect) { if (NetworkInterface.GetIsNetworkAvailable()) { Reconnect(); } else { Debuger.Log("等待重连,但是网络不可用!"); } } CheckTimeout(); } public string ToDebugString() { return string.Format("ip:{0}, port:{1}", m_ip, m_port); } } } ================================================ FILE: SGFCore/Network/FSPLite/Client/FSPFrameController.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 帧同步模块 * Frame synchronization module * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ namespace SGF.Network.FSPLite.Client { public class FSPFrameController { //缓冲控制 private int m_ClientFrameRateMultiple = 2; private int m_JitterBuffSize = 0; private bool m_IsInBuffing = false; private int m_NewestFrameId; //加速控制 private bool m_EnableSpeedUp = true; private int m_DefaultSpeed = 1; private bool m_IsInSpeedUp = false; //自动缓冲 private bool m_EnableAutoBuff = true; private int m_AutoBuffCnt = 0; private int m_AutoBuffInterval = 15; public bool IsInBuffing { get { return m_IsInBuffing; } } public bool IsInSpeedUp { get { return m_IsInSpeedUp; } } public int JitterBufferSize { get { return m_JitterBuffSize; } set { m_JitterBuffSize = value; } } public int NewestFrameId { get { return m_NewestFrameId; } } public void Start(FSPParam param) { SetParam(param); } public void Stop() { } public void SetParam(FSPParam param) { m_ClientFrameRateMultiple = param.clientFrameRateMultiple; m_JitterBuffSize = param.jitterBufferSize; m_EnableSpeedUp = param.enableSpeedUp; m_DefaultSpeed = param.defaultSpeed; m_EnableAutoBuff = param.enableAutoBuffer; } public void AddFrameId(int frameId) { m_NewestFrameId = frameId; } public int GetFrameSpeed(int curFrameId) { int speed = 0; var newFrameNum = m_NewestFrameId - curFrameId; //是否正在缓冲中 if (!m_IsInBuffing) { //没有在缓冲中 if (newFrameNum == 0) { //需要缓冲一下 m_IsInBuffing = true; m_AutoBuffCnt = m_AutoBuffInterval; } else { //因为即将播去这么多帧 newFrameNum -= m_DefaultSpeed; int speedUpFrameNum = newFrameNum - m_JitterBuffSize; if (speedUpFrameNum >= m_ClientFrameRateMultiple) { //可以加速 if (m_EnableSpeedUp) { speed = 2; if (speedUpFrameNum > 100) { speed = 8; } else if (speedUpFrameNum > 50) { speed = 4; } } else { speed = m_DefaultSpeed; } } else { //还达不到可加速的帧数 speed = m_DefaultSpeed; if (m_EnableAutoBuff) { m_AutoBuffCnt--; if (m_AutoBuffCnt <= 0) { m_AutoBuffCnt = m_AutoBuffInterval; if (speedUpFrameNum < m_ClientFrameRateMultiple - 1) { //这个时候大概率接下来会缺帧 speed = 0; } } } } } } else { //正在缓冲中 int speedUpFrameNum = newFrameNum - m_JitterBuffSize; if (speedUpFrameNum > 0) { m_IsInBuffing = false; } } m_IsInSpeedUp = speed > m_DefaultSpeed; return speed; } } } ================================================ FILE: SGFCore/Network/FSPLite/Client/FSPManager.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 帧同步模块 * Frame synchronization module * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using SGF.Extension; using SGF.Utils; namespace SGF.Network.FSPLite.Client { public class FSPManager:ILogTag { public string LOG_TAG { get; private set; } //来自帧同步服务器的事件 public event Action onGameBegin; public event Action onRoundBegin; public event Action onControlStart; public event Action onRoundEnd; public event Action onGameEnd; public event Action onGameExit; //基础参数 private bool m_IsRunning = false; private FSPClient m_Client; private FSPParam m_Param; private uint m_MinePlayerId; private Action m_FrameListener; private int m_CurrentFrameIndex; private int m_LockedFrameIndex; public uint MainPlayerId { get { return m_MinePlayerId; } } //游戏状态 private FSPGameState m_GameState = FSPGameState.None; public FSPGameState GameState { get { return m_GameState; } } //帧列表 private DictionarySafe m_FrameBuffer;//缓存的帧 private FSPFrameController m_FrameCtrl; public FSPFrameController FrameController { get { return m_FrameCtrl; } } //本地模拟 private FSPFrame m_NextLocalFrame; public void Start(FSPParam param, uint playerId) { m_Param = param; m_MinePlayerId = playerId; LOG_TAG = "FSPManager[" + playerId + "]"; Debuger.Log(); if (m_Param.useLocal) { m_LockedFrameIndex = param.maxFrameId; } else { m_Client = new FSPClient(); m_Client.Init(m_Param.sid); m_Client.SetFSPAuthInfo(param.authId); m_Client.SetFSPListener(OnFSPListener); m_Client.Connect(param.host, param.port); m_Client.VerifyAuth(); m_LockedFrameIndex = m_Param.clientFrameRateMultiple - 1; } m_IsRunning = true; m_GameState = FSPGameState.Create; m_FrameBuffer = new DictionarySafe(); m_CurrentFrameIndex = 0; m_FrameCtrl = new FSPFrameController(); m_FrameCtrl.Start(param); } public void Stop() { Debuger.Log(); m_GameState = FSPGameState.None; if (m_Client != null) { m_Client.Clean(); m_Client = null; } m_FrameListener = null; m_FrameCtrl.Stop(); m_FrameBuffer.Clear(); m_IsRunning = false; onGameBegin = null; onRoundBegin = null; onControlStart = null; onGameEnd = null; onRoundEnd = null; } /// /// 设置帧数据的监听 /// /// public void SetFrameListener(Action listener) { Debuger.Log(); m_FrameListener = listener; } /// /// 监听来自FSPClient的帧数据 /// /// private void OnFSPListener(FSPFrame frame) { AddServerFrame(frame); } private void AddServerFrame(FSPFrame frame) { if (frame.frameId <= 0) { ExecuteFrame(frame.frameId, frame); return; } frame.frameId = frame.frameId * m_Param.clientFrameRateMultiple; m_LockedFrameIndex = frame.frameId + m_Param.clientFrameRateMultiple - 1; m_FrameBuffer.Add(frame.frameId, frame); m_FrameCtrl.AddFrameId(frame.frameId); } #region 对基础流程Cmd的处理 public void SendGameBegin() { Debuger.Log(); SendFSP(FSPBasicCmd.GAME_BEGIN, 0); } private void Handle_GameBegin(int arg) { Debuger.Log(arg); m_GameState = FSPGameState.GameBegin; if (onGameBegin != null) { onGameBegin(arg); } } public void SendRoundBegin() { Debuger.Log(); SendFSP(FSPBasicCmd.ROUND_BEGIN, 0); } private void Handle_RoundBegin(int arg) { Debuger.Log(arg); m_GameState = FSPGameState.RoundBegin; m_CurrentFrameIndex = 0; if (!m_Param.useLocal) { m_LockedFrameIndex = m_Param.clientFrameRateMultiple - 1; } else { m_LockedFrameIndex = m_Param.maxFrameId; } m_FrameBuffer.Clear(); if (onRoundBegin != null) { onRoundBegin(arg); } } public void SendControlStart() { Debuger.Log(); SendFSP(FSPBasicCmd.CONTROL_START, 0); } private void Handle_ControlStart(int arg) { Debuger.Log(arg); m_GameState = FSPGameState.ControlStart; if (onControlStart != null) { onControlStart(arg); } } public void SendRoundEnd() { Debuger.Log(); SendFSP(FSPBasicCmd.ROUND_END, 0); } private void Handle_RoundEnd(int arg) { Debuger.Log(arg); m_GameState = FSPGameState.RoundEnd; if (onRoundEnd != null) { onRoundEnd(arg); } } public void SendGameEnd() { Debuger.Log(); SendFSP(FSPBasicCmd.GAME_END, 0); } private void Handle_GameEnd(int arg) { Debuger.Log(arg); m_GameState = FSPGameState.GameEnd; if (onGameEnd != null) { onGameEnd(arg); } } public void SendGameExit() { Debuger.Log(); SendFSP(FSPBasicCmd.GAME_EXIT, 0); } private void Handle_GameExit(uint playerId) { Debuger.Log(playerId); if (onGameExit != null) { onGameExit(playerId); } } #endregion /// /// 给外界用来发送FSPCmd的 /// /// /// public void SendFSP(int cmd, params int[] args) { if (!m_IsRunning) { return; } if (m_Param.useLocal) { SendFSPLocal(cmd, args); } else { m_Client.SendFSP(m_CurrentFrameIndex, cmd, args); } } /// /// 用于本地兼容,比如打PVE的时候,也可以用帧同步兼容 /// /// /// private void SendFSPLocal(int cmd, int[] args) { Debuger.Log("vkey={0}, arg={1}", cmd, args.ToListString()); if (m_NextLocalFrame == null || m_NextLocalFrame.frameId != m_CurrentFrameIndex + 1) { m_NextLocalFrame = new FSPFrame(); m_NextLocalFrame.frameId = m_CurrentFrameIndex + 1; m_FrameBuffer.Add(m_NextLocalFrame.frameId, m_NextLocalFrame); } FSPMessage msg = new FSPMessage(); msg.cmd = cmd; msg.args = args; msg.playerId = m_MinePlayerId; m_NextLocalFrame.msgs.Add(msg); } /// /// 由外界驱动 /// public void Tick() { if (!m_IsRunning) { return; } if (m_Param.useLocal) { if (m_LockedFrameIndex == 0 || m_LockedFrameIndex > m_CurrentFrameIndex) { m_CurrentFrameIndex++; var frame = m_FrameBuffer[m_CurrentFrameIndex]; ExecuteFrame(m_CurrentFrameIndex, frame); } } else { m_Client.Tick(); int speed = m_FrameCtrl.GetFrameSpeed(m_CurrentFrameIndex); while (speed > 0) { if (m_CurrentFrameIndex < m_LockedFrameIndex) { m_CurrentFrameIndex++; var frame = m_FrameBuffer[m_CurrentFrameIndex]; ExecuteFrame(m_CurrentFrameIndex, frame); } speed--; } } } /// /// 执行每一帧 /// /// /// private void ExecuteFrame(int frameId, FSPFrame frame) { if (frame !=null && !frame.IsEmpty()) { for (int i = 0; i < frame.msgs.Count; i++) { var msg = frame.msgs[i]; switch (msg.cmd) { case FSPBasicCmd.GAME_BEGIN: Handle_GameBegin(msg.args[0]);break; case FSPBasicCmd.ROUND_BEGIN: Handle_RoundBegin(msg.args[0]); break; case FSPBasicCmd.CONTROL_START: Handle_ControlStart(msg.args[0]); break; case FSPBasicCmd.ROUND_END: Handle_RoundEnd(msg.args[0]); break; case FSPBasicCmd.GAME_END: Handle_GameEnd(msg.args[0]); break; case FSPBasicCmd.GAME_EXIT: Handle_GameExit(msg.playerId); break; } } } if (m_FrameListener != null) { m_FrameListener(frameId, frame); } } //====================================================================== public string ToDebugString() { string str = ""; if (m_FrameCtrl != null) { str += ("NewestFrameId:" + m_FrameCtrl.NewestFrameId) + "; "; str += ("PlayedFrameId:" + m_CurrentFrameIndex) + "; "; str += ("IsInBuffing:" + m_FrameCtrl.IsInBuffing) + "; "; str += ("IsInSpeedUp:" + m_FrameCtrl.IsInSpeedUp) + "; "; str += ("FrameBufferSize:" + m_FrameCtrl.JitterBufferSize) + "; "; } if (m_Client != null) { str += m_Client.ToDebugString(); } return str; } } } ================================================ FILE: SGFCore/Network/FSPLite/FSPBasicCmd.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 帧同步模块 * Frame synchronization module * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ namespace SGF.Network.FSPLite { public class FSPBasicCmd { /// /// PVP战斗结束 /// public const int GAME_BEGIN = 1000; /// /// 对局开始 /// public const int ROUND_BEGIN = 1001; /// /// 开始加载 /// public const int LOAD_START = 1002; /// /// 加载进度条 /// public const int LOAD_PROGRESS = 1003; /// /// 可以开始控制... /// public const int CONTROL_START = 1004; /// /// 发送中途退出 /// public const int GAME_EXIT = 1005; /// /// 对局结束 /// public const int ROUND_END = 1006; /// /// PVP战斗结束 /// public const int GAME_END = 1007; /// /// 鉴权身份字段 /// public const int AUTH = 1008; /// /// PING 响应回包... /// public const int PING = 1009; } } ================================================ FILE: SGFCore/Network/FSPLite/FSPGameEndReason.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 帧同步模块 * Frame synchronization module * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ namespace SGF.Network.FSPLite { //由于以上有多种可能发GameEnd的情况,所以这里有一个GameEnd的原因定义 public enum FSPGameEndReason { Normal = 0, //正常结束 AllOtherExit = 1, //所有其他人都主动退出了 AllOtherLost = 2, //所有其他人都掉线了 } } ================================================ FILE: SGFCore/Network/FSPLite/FSPGameState.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 帧同步模块 * Frame synchronization module * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ namespace SGF.Network.FSPLite { public enum FSPGameState { /// /// 0 初始状态 /// None = 0, /// /// 游戏创建状态 /// 只有在该状态下,才允许加入玩家 /// 当所有玩家都发VKey.GameBegin后,进入下一个状态 /// Create, /// /// 游戏开始状态 /// 在该状态下,等待所有玩家发VKey.RoundBegin,或者 判断玩家是否掉线 /// 当所有人都发送VKey.RoundBegin,进入下一个状态 /// 当有玩家掉线,则从FSPGame中删除该玩家: /// 判断如果只剩下1个玩家了,则直接进入GameEnd状态,否则不影响游戏状态 /// GameBegin, /// /// 回合开始状态 /// (这个时候客户端可能在加载资源) /// 在该状态下,等待所有玩家发VKey.ControlStart, 或者 判断玩家是否掉线 /// 当所有人都发送VKey.ControlStart,进入下一个状态 /// 当有玩家掉线,则从FSPGame中删除该玩家: /// 判断如果只剩下1个玩家了,则直接进入GameEnd状态,否则不影响游戏状态 /// RoundBegin, /// /// 可以开始操作状态 /// (因为每个回合可能都会有加载过程,不同的玩家加载速度可能不同,需要用一个状态统一一下) /// 在该状态下,接收玩家的业务VKey, 或者 VKey.RoundEnd,或者VKey.GameExit /// 当所有人都发送VKey.RoundEnd,进入下一个状态 /// 当有玩家掉线,或者发送VKey.GameExit,则从FSPGame中删除该玩家: /// 判断如果只剩下1个玩家了,则直接进入GameEnd状态,否则不影响游戏状态 /// ControlStart, /// /// 回合结束状态 /// (大部分游戏只有1个回合,也有些游戏有多个回合,由客户端逻辑决定) /// 在该状态下,等待玩家发送VKey.GameEnd,或者 VKey.RoundBegin(如果游戏不只1个回合的话) /// 当所有人都发送VKey.GameEnd,或者 VKey.RoundBegin时,进入下一个状态 /// 当有玩家掉线,则从FSPGame中删除该玩家: /// 判断如果只剩下1个玩家了,则直接进入GameEnd状态,否则不影响游戏状态 /// RoundEnd, /// /// 游戏结束状态 /// 在该状态下,不再接收任何Vkey,然后给所有玩家发VKey.GameEnd,并且等待FSPServer关闭 /// GameEnd } } ================================================ FILE: SGFCore/Network/FSPLite/FSPLiteData.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 帧同步模块 * Frame synchronization module * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System.Collections.Generic; using System.Text; using ProtoBuf; using SGF.Codec; using SGF.Extension; namespace SGF.Network.FSPLite { //========================================================== #region FSP启动参数定义 [ProtoContract] public class FSPParam { [ProtoMember(1)] public string host; [ProtoMember(2)] public int port; [ProtoMember(3)] public uint sid; [ProtoMember(4)] public int serverFrameInterval = 66; [ProtoMember(5)] public int serverTimeout = 15000;//ms [ProtoMember(6)] public int clientFrameRateMultiple = 2; [ProtoMember(7)] public int authId = 0; [ProtoMember(8)] public bool useLocal = false; [ProtoMember(9)] public int maxFrameId = 1800; [ProtoMember(10)] public bool enableSpeedUp = true; [ProtoMember(11)] public int defaultSpeed = 1; [ProtoMember(12)] public int jitterBufferSize = 0;//缓冲大小 [ProtoMember(13)] public bool enableAutoBuffer = true; public FSPParam Clone() { byte[] buffer = PBSerializer.NSerialize(this); return (FSPParam)PBSerializer.NDeserialize(buffer, typeof(FSPParam)); } public string ToString(string prefix = "") { StringBuilder sb = new StringBuilder(); sb.AppendFormat("\n{0}host:{1}:{2}", prefix, host, port); sb.AppendFormat("\n{0}serverFrameInterval:{1}", prefix, serverFrameInterval); sb.AppendFormat("\n{0}clientFrameRateMultiple:{1}", prefix, clientFrameRateMultiple); sb.AppendFormat("\n{0}serverTimeout:{1}", prefix, serverTimeout); sb.AppendFormat("\n{0}maxFrameId:{1}", prefix, maxFrameId); return sb.ToString(); } } #endregion [ProtoContract] public class FSPMessage { [ProtoMember(1)] public int cmd; [ProtoMember(2)] public int[] args; [ProtoMember(3)] public int custom; public uint playerId { get { return (uint)custom; } set { custom = (int)value; } } public int clientFrameId { get { return custom; } set { custom = value; } } public override string ToString() { if (args != null) { return string.Format("cmd:{0}, args:{1}, custom:{2}", cmd, args.ToListString(), custom); } else { return string.Format("cmd:{0}, args:{1}, custom:{2}", cmd, "[]", custom); } } } [ProtoContract] public class FSPDataC2S { [ProtoMember(1)] public uint sid = 0; [ProtoMember(2)] public List msgs = new List(); } [ProtoContract] public class FSPDataS2C { [ProtoMember(1)] public List frames = new List(); } [ProtoContract] public class FSPFrame { [ProtoMember(1)] public int frameId; [ProtoMember(2)] public List msgs = new List(); public bool IsEmpty() { return (msgs == null || msgs.Count == 0); } public bool Contains(int cmd) { if (!IsEmpty()) { for (int i = 0; i < msgs.Count; i++) { if (msgs[i].cmd == cmd) { return true; } } } return false; } public override string ToString() { string tmp = ""; for (int i = 0; i < msgs.Count - 1; i++) { tmp += msgs[i] + ","; } if (msgs.Count > 0) { tmp += msgs[msgs.Count - 1].ToString(); } return string.Format("frameId:{0}, msgs:[{1}]", frameId, tmp); } } } ================================================ FILE: SGFCore/Network/FSPLite/Server/FSPGame.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 帧同步模块 * Frame synchronization module * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Text; using SGF.Extension; namespace SGF.Network.FSPLite.Server { public class FSPGame { public static int ActiveTimeout = 10; //有一个玩家退出游戏 public Action onGameExit; //游戏真正结束 public Action onGameEnd; /// /// 最大支持的玩家数:31 /// 因为用来保存玩家Flag的Int只有31位有效位可用,不过31已经足够了 /// private const int MaxPlayerNum = 31; //基础参数 private int m_authId; private uint m_gameId; public uint id { get { return m_gameId; } } //游戏状态 private FSPGameState m_State; private int m_StateParam1; private int m_StateParam2; public FSPGameState State { get { return m_State; } } //Player的Cmd标识 private int m_GameBeginFlag = 0; private int m_RoundBeginFlag = 0; private int m_ControlStartFlag = 0; private int m_RoundEndFlag = 0; private int m_GameEndFlag = 0; //Round标志 private int m_CurRoundId = 0; public int CurrentRoundId { get { return m_CurRoundId; } } //服务器的当前帧 private FSPFrame m_LockedFrame = new FSPFrame(); private int m_CurFrameId = 0; //玩家列表 private List m_ListPlayer = new List(); private List m_ListPlayersExitOnNextFrame = new List(); //--------------------------------------------------------- public void Create(uint gameId, int authId) { Debuger.Log(); m_authId = authId; m_gameId = gameId; m_CurRoundId = 0; SetGameState(FSPGameState.Create); } public void Release() { SetGameState(FSPGameState.None); for (int i = 0; i < m_ListPlayer.Count; i++) { FSPPlayer player = m_ListPlayer[i]; player.Release(); } m_ListPlayer.Clear(); m_ListPlayersExitOnNextFrame.Clear(); onGameExit = null; onGameEnd = null; Debuger.Log(); } public string ToString(string prefix = "") { StringBuilder sb = new StringBuilder(); sb.AppendFormat("[{0}] AuthId:{1}, State:{2}, CurrentRound:{3}, CurrentFrameId:{4}",m_gameId, m_authId, m_State, m_CurRoundId, m_CurFrameId); sb.AppendFormat("\n{0}PlayerList:", prefix); for (int i = 0; i < m_ListPlayer.Count; i++) { sb.AppendFormat("\n{0}Player{1}", prefix, m_ListPlayer[i].ToString(prefix + "\t")); } sb.AppendFormat("\n{0}ListPlayersExitOnNextFrame:", prefix); for (int i = 0; i < m_ListPlayersExitOnNextFrame.Count; i++) { sb.AppendFormat("\n{0}Player{1}", prefix, m_ListPlayersExitOnNextFrame[i].ToString(prefix + "\t")); } return sb.ToString(); } //=================================================================== public FSPPlayer AddPlayer(uint playerId, FSPSession session) { Debuger.Log("playerId:{0}", playerId); if (m_State != FSPGameState.Create) { Debuger.LogError("当前状态下无法AddPlayer! State = {0}", m_State); return null; } FSPPlayer player = null; for (int i = 0; i < m_ListPlayer.Count; i++) { player = m_ListPlayer[i]; if (player.id == playerId) { Debuger.LogWarning("PlayerId已经存在!用新的替代旧的! PlayerId = " + playerId); m_ListPlayer.RemoveAt(i); player.Release(); break; } } if (m_ListPlayer.Count >= MaxPlayerNum) { Debuger.LogError("已经达到最大玩家数了! MaxPlayerNum = {0}", MaxPlayerNum); return null; } player = new FSPPlayer(); player.Create(playerId, m_authId, session, OnRecvFromPlayer); m_ListPlayer.Add(player); return player; } private FSPPlayer GetPlayer(uint playerId) { FSPPlayer player = null; for (int i = 0; i < m_ListPlayer.Count; i++) { player = m_ListPlayer[i]; if (player.id == playerId) { return player; } } return null; } internal int GetPlayerCount() { return m_ListPlayer.Count; } public List GetPlayerList() { return m_ListPlayer; } //--------------------------------------------------------- //收到客户端Player的Cmd private void OnRecvFromPlayer(FSPPlayer player, FSPMessage msg) { HandleClientCmd(player, msg); } protected virtual void HandleClientCmd(FSPPlayer player, FSPMessage msg) { uint playerId = player.id; //处理鉴权 if (!player.HasAuthed) { if (msg.cmd == FSPBasicCmd.AUTH) { player.SetAuth(msg.args[0]); } else { Debuger.LogWarning("当前Player未鉴权,无法处理该Cmd:{0}", msg.cmd); } return; } switch (msg.cmd) { case FSPBasicCmd.GAME_BEGIN: { Debuger.Log("GAME_BEGIN, playerId = {0}, cmd = {1}", playerId, msg); SetFlag(playerId, ref m_GameBeginFlag, "m_GameBeginFlag"); break; } case FSPBasicCmd.ROUND_BEGIN: { Debuger.Log("ROUND_BEGIN, playerId = {0}, cmd = {1}", playerId, msg); SetFlag(playerId, ref m_RoundBeginFlag, "m_RoundBeginFlag"); break; } case FSPBasicCmd.CONTROL_START: { Debuger.Log("CONTROL_START, playerId = {0}, cmd = {1}", playerId, msg); SetFlag(playerId, ref m_ControlStartFlag, "m_ControlStartFlag"); break; } case FSPBasicCmd.ROUND_END: { Debuger.Log("ROUND_END, playerId = {0}, cmd = {1}", playerId, msg); SetFlag(playerId, ref m_RoundEndFlag, "m_RoundEndFlag"); break; } case FSPBasicCmd.GAME_END: { Debuger.Log("GAME_END, playerId = {0}, cmd = {1}", playerId, msg); SetFlag(playerId, ref m_GameEndFlag, "m_GameEndFlag"); break; } case FSPBasicCmd.GAME_EXIT: { Debuger.Log("GAME_EXIT, playerId = {0}, cmd = {1}", playerId, msg); HandleGameExit(playerId, msg); break; } default: { Debuger.Log("playerId = {0}, cmd = {1}", playerId, msg); AddCmdToCurrentFrame(playerId, msg); break; } } } private void AddCmdToCurrentFrame(uint playerId, FSPMessage msg) { msg.playerId = playerId; m_LockedFrame.msgs.Add(msg); } private void AddBasicCmdToCurrentFrame(int cmd, int arg = 0) { FSPMessage msg = new FSPMessage(); msg.cmd = cmd; msg.args = new[] {arg}; AddCmdToCurrentFrame(0, msg); } private void HandleGameExit(uint playerId, FSPMessage msg) { AddCmdToCurrentFrame(playerId, msg); FSPPlayer player = GetPlayer(playerId); if (player != null) { player.WaitForExit = true; if (onGameExit != null) { onGameExit(player.id); } } } //======================================================================================= /// /// 驱动游戏状态 /// public void EnterFrame() { for (int i = 0; i < m_ListPlayersExitOnNextFrame.Count; i++) { var player = m_ListPlayersExitOnNextFrame[i]; player.Release(); } m_ListPlayersExitOnNextFrame.Clear(); //处理游戏状态切换 HandleGameState(); //经过上面状态处理之后,有可能状态还会发生变化 if (m_State == FSPGameState.None) { return; } if (m_LockedFrame.frameId != 0 || !m_LockedFrame.IsEmpty()) { //将当前帧扔级Player for (int i = 0; i < m_ListPlayer.Count; i++) { FSPPlayer player = m_ListPlayer[i]; player.SendToClient(m_LockedFrame); if (player.WaitForExit) { m_ListPlayersExitOnNextFrame.Add(player); m_ListPlayer.RemoveAt(i); --i; } } } //0帧每个循环需要额外清除掉再重新统计 if (m_LockedFrame.frameId == 0) { m_LockedFrame = new FSPFrame(); } //在这个阶段,帧号才会不停往上加 if (m_State == FSPGameState.RoundBegin || m_State == FSPGameState.ControlStart) { m_CurFrameId++; m_LockedFrame = new FSPFrame(); m_LockedFrame.frameId = m_CurFrameId; } } //设置状态机 protected void SetGameState(FSPGameState state, int param1 = 0, int param2 = 0) { Debuger.Log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); Debuger.Log("{0} -> {1}, param1 = {2}, param2 = {3}", m_State, state, param1, param2); Debuger.Log("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); m_State = state; m_StateParam1 = param1; m_StateParam2 = param2; } private void HandleGameState() { switch (m_State) { case FSPGameState.None: { //进入这个状态的游戏,马上将会被回收 //这里是否要考虑session中的所有消息都发完了? break; } case FSPGameState.Create: //游戏刚创建,未有任何玩家加入, 这个阶段等待玩家加入 { OnState_Create(); break; } case FSPGameState.GameBegin: //游戏开始,等待RoundBegin { OnState_GameBegin(); break; } case FSPGameState.RoundBegin: //回合已经开始,开始加载资源等,等待ControlStart { OnState_RoundBegin(); break; } case FSPGameState.ControlStart: //在这个阶段可操作,这时候接受游戏中的各种行为包,并等待RoundEnd { OnState_ControlStart(); break; } case FSPGameState.RoundEnd: //回合已经结束,判断是否进行下一轮,即等待RoundBegin,或者GameEnd { OnState_RoundEnd(); break; } case FSPGameState.GameEnd://游戏结束 { OnState_GameEnd(); break; } default: break; } } protected virtual int OnState_Create() { //如果有任何一方已经鉴权完毕,则游戏进入GameBegin状态准备加载 if (IsFlagFull(m_GameBeginFlag)) { SetGameState(FSPGameState.GameBegin); AddBasicCmdToCurrentFrame(FSPBasicCmd.GAME_BEGIN); return 0; } return 0; } /// /// 游戏开始状态 /// 在该状态下,等待所有玩家发VKey.RoundBegin,或者 判断玩家是否掉线 /// 当所有人都发送VKey.RoundBegin,进入下一个状态 /// 当有玩家掉线,则从FSPGame中删除该玩家: /// 判断如果只剩下1个玩家了,则直接进入GameEnd状态,否则不影响游戏状态 /// protected virtual int OnState_GameBegin() { if (CheckGameAbnormalEnd()) { return 0; } if (IsFlagFull(m_RoundBeginFlag)) { SetGameState(FSPGameState.RoundBegin); IncRoundId(); ClearRound(); AddBasicCmdToCurrentFrame(FSPBasicCmd.ROUND_BEGIN, m_CurRoundId); return 0; } return 0; } /// /// 回合开始状态 /// (这个时候客户端可能在加载资源) /// 在该状态下,等待所有玩家发VKey.ControlStart, 或者 判断玩家是否掉线 /// 当所有人都发送VKey.ControlStart,进入下一个状态 /// 当有玩家掉线,则从FSPGame中删除该玩家: /// 判断如果只剩下1个玩家了,则直接进入GameEnd状态,否则不影响游戏状态 /// protected virtual int OnState_RoundBegin() { if (CheckGameAbnormalEnd()) { return 0; } if (IsFlagFull(m_ControlStartFlag)) { ResetRoundFlag(); SetGameState(FSPGameState.ControlStart); AddBasicCmdToCurrentFrame(FSPBasicCmd.CONTROL_START); return 0; } return 0; } /// /// 可以开始操作状态 /// (因为每个回合可能都会有加载过程,不同的玩家加载速度可能不同,需要用一个状态统一一下) /// 在该状态下,接收玩家的业务VKey, 或者 VKey.RoundEnd,或者VKey.GameExit /// 当所有人都发送VKey.RoundEnd,进入下一个状态 /// 当有玩家掉线,或者发送VKey.GameExit,则从FSPGame中删除该玩家: /// 判断如果只剩下1个玩家了,则直接进入GameEnd状态,否则不影响游戏状态 /// protected virtual int OnState_ControlStart() { if (CheckGameAbnormalEnd()) { return 0; } if (IsFlagFull(m_RoundEndFlag)) { SetGameState(FSPGameState.RoundEnd); ClearRound(); AddBasicCmdToCurrentFrame(FSPBasicCmd.ROUND_END, m_CurRoundId); return 0; } return 0; } /// /// 回合结束状态 /// (大部分游戏只有1个回合,也有些游戏有多个回合,由客户端逻辑决定) /// 在该状态下,等待玩家发送VKey.GameEnd,或者 VKey.RoundBegin(如果游戏不只1个回合的话) /// 当所有人都发送VKey.GameEnd,或者 VKey.RoundBegin时,进入下一个状态 /// 当有玩家掉线,则从FSPGame中删除该玩家: /// 判断如果只剩下1个玩家了,则直接进入GameEnd状态,否则不影响游戏状态 /// protected virtual int OnState_RoundEnd() { if (CheckGameAbnormalEnd()) { return 0; } //这是正常GameEnd if (IsFlagFull(m_GameEndFlag)) { SetGameState(FSPGameState.GameEnd, (int)FSPGameEndReason.Normal); AddBasicCmdToCurrentFrame(FSPBasicCmd.GAME_END, (int)FSPGameEndReason.Normal); return 0; } if (IsFlagFull(m_RoundBeginFlag)) { SetGameState(FSPGameState.RoundBegin); ClearRound(); IncRoundId(); AddBasicCmdToCurrentFrame(FSPBasicCmd.ROUND_BEGIN, m_CurRoundId); return 0; } return 0; } protected virtual int OnState_GameEnd() { //到这里就等业务层去读取数据了 if (onGameEnd != null) { onGameEnd(m_StateParam1); onGameEnd = null; } return 0; } public bool IsGameEnd() { return m_State == FSPGameState.GameEnd; } //============================================================ /// /// 检测游戏是否异常结束 /// private bool CheckGameAbnormalEnd() { //判断还剩下多少玩家,如果玩家少于2,则表示至少有玩家主动退出 if (m_ListPlayer.Count < 1) { //直接进入GameEnd状态 SetGameState(FSPGameState.GameEnd, (int)FSPGameEndReason.AllOtherExit); AddBasicCmdToCurrentFrame(FSPBasicCmd.GAME_END, (int)FSPGameEndReason.AllOtherExit); return true; } // 检测玩家在线状态 for (int i = 0; i < m_ListPlayer.Count; i++) { FSPPlayer player = m_ListPlayer[i]; if (player.IsLose()) { m_ListPlayer.RemoveAt(i); player.Release(); --i; } } //判断还剩下多少玩家,如果玩家少于1,则表示至少有玩家主动退出 if (m_ListPlayer.Count < 1) { //直接进入GameEnd状态 SetGameState(FSPGameState.GameEnd, (int)FSPGameEndReason.AllOtherLost); AddBasicCmdToCurrentFrame(FSPBasicCmd.GAME_END, (int)FSPGameEndReason.AllOtherLost); return true; } return false; } private void IncRoundId() { ++m_CurRoundId; } private int ClearRound() { m_LockedFrame = new FSPFrame(); m_CurFrameId = 0; ResetRoundFlag(); for (int i = 0; i < m_ListPlayer.Count; i++) { if (m_ListPlayer[i] != null) { m_ListPlayer[i].ClearRound(); } } return 0; } private void ResetRoundFlag() { m_RoundBeginFlag = 0; m_ControlStartFlag = 0; m_RoundEndFlag = 0; m_GameEndFlag = 0; } //============================================================ //-------------------------------------------------------------------- #region Player 状态标志工具函数 private void SetFlag(uint playerId, ref int flag, string flagname) { flag |= (0x01 << ((int)playerId - 1)); Debuger.Log("player = {0}, flag = {1}", playerId, flagname); } private void ClsFlag(int playerId, ref int flag, string flagname) { flag &= (~(0x01 << (playerId - 1))); } public bool IsAnyFlagSet(int flag) { return flag != 0; } public bool IsFlagFull(int flag) { if (m_ListPlayer.Count > 0) { for (int i = 0; i < m_ListPlayer.Count; i++) { FSPPlayer player = m_ListPlayer[i]; int playerId = (int)player.id; if ((flag & (0x01 << (playerId - 1))) == 0) { return false; } } return true; } return false; } #endregion } } ================================================ FILE: SGFCore/Network/FSPLite/Server/FSPGateway.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 帧同步模块 * Frame synchronization module * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using SGF.Network.Core; using SGF.Utils; namespace SGF.Network.FSPLite.Server { public class FSPGateway { private static uint ms_lastSid = 0; public static uint NewSessionID() { return ++ms_lastSid; } //===================================================================== //基础数据 private bool m_IsRunning = false; public bool IsRunning { get { return m_IsRunning; } } //线程模块 private Thread m_ThreadRecv; //通讯部分 private Socket m_SystemSocket; private byte[] m_RecvBufferTemp = new byte[4096]; private NetBufferReader m_RecvBufferTempReader = new NetBufferReader(); private int m_port; //Session管理 private MapList m_mapSession; public void Init(int port) { Debuger.Log("port:{0}", port); m_port = port; m_mapSession = new MapList(); Start(); } public void Clean() { Debuger.Log(); m_mapSession.Clear(); Close(); } public int Port { get { return (m_SystemSocket.LocalEndPoint as IPEndPoint).Port; } } public string Host { get { return IPUtils.SelfIP; } } public void Dump() { StringBuilder sb = new StringBuilder(); var dic = m_mapSession.AsDictionary(); foreach (var pair in dic) { var session = pair.Value; sb.AppendLine("\t" + session.ToString()); } Debuger.LogWarning("\nFSPGateway Sessions ({0}):\n{1}", m_mapSession.Count, sb); } public void Start() { Debuger.Log(); m_IsRunning = true; m_SystemSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); m_SystemSocket.Bind(IPUtils.GetIPEndPointAny(AddressFamily.InterNetwork, m_port)); m_ThreadRecv = new Thread(Thread_Recv) { IsBackground = true }; m_ThreadRecv.Start(); } public void Close() { Debuger.Log(); m_IsRunning = false; if (m_ThreadRecv != null) { m_ThreadRecv.Interrupt(); m_ThreadRecv = null; } if (m_SystemSocket != null) { try { m_SystemSocket.Shutdown(SocketShutdown.Both); } catch (Exception e) { Debuger.LogWarning(e.Message + e.StackTrace); } m_SystemSocket.Close(); m_SystemSocket = null; } } public FSPSession CreateSession() { Debuger.Log(); uint sid = NewSessionID(); FSPSession session = new FSPSession(sid, HandleSessionSend); m_mapSession.Add(sid, session); return session; } public FSPSession GetSession(uint sid) { FSPSession session = null; lock (m_mapSession) { session = m_mapSession[sid]; } return session; } private void HandleSessionSend(IPEndPoint remoteEndPoint, byte[] buffer, int size) { if (m_SystemSocket != null) { int cnt = m_SystemSocket.SendTo(buffer, 0, size, SocketFlags.None, remoteEndPoint); } else { Debuger.LogError("Socket已经关闭!"); } } //================================================================================= //接收线程 //================================================================================= private void Thread_Recv() { while (m_IsRunning) { try { DoReceiveInThread(); } catch (Exception e) { Debuger.LogWarning(e.Message + "\n" + e.StackTrace); Thread.Sleep(1); } } } private void DoReceiveInThread() { EndPoint remotePoint = IPUtils.GetIPEndPointAny(AddressFamily.InterNetwork, 0); int cnt = m_SystemSocket.ReceiveFrom(m_RecvBufferTemp, m_RecvBufferTemp.Length, SocketFlags.None, ref remotePoint); if (cnt > 0) { m_RecvBufferTempReader.Attach(m_RecvBufferTemp, cnt); byte[] m_32b = new byte[4]; m_RecvBufferTempReader.ReadBytes(m_32b, 0, 4); uint sid = BitConverter.ToUInt32(m_32b, 0); lock (m_mapSession) { FSPSession session = null; if (sid == 0) { Debuger.LogError("基于KCP的Sid为0,该包需要被丢掉"); } else { session = m_mapSession[sid]; } if (session != null) { session.Active(remotePoint as IPEndPoint); session.DoReceiveInGateway(m_RecvBufferTemp, cnt); } else { Debuger.LogWarning("无效的包! sid:{0}", sid); } } } } //================================================================================= //时钟信号 //================================================================================= private uint m_lastClearSessionTime = 0; public void Tick() { if (m_IsRunning) { lock (m_mapSession) { uint current = (uint)TimeUtils.GetTotalMillisecondsSince1970(); if (current - m_lastClearSessionTime > FSPSession.ActiveTimeout * 1000 / 2) { m_lastClearSessionTime = current; ClearNoActiveSession(); } var list = m_mapSession.AsList(); int cnt = list.Count; for (int i = 0; i < cnt; i++) { var session = list[i]; session.Tick(current); } } } } private void ClearNoActiveSession() { var list = m_mapSession.AsList(); var dir = m_mapSession.AsDictionary(); int cnt = list.Count; for (int i = cnt - 1; i >= 0; i--) { var session = list[i]; if (!session.IsActived()) { list.RemoveAt(i); dir.Remove(session.id); } } } } } ================================================ FILE: SGFCore/Network/FSPLite/Server/FSPManager.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 帧同步模块 * Frame synchronization module * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Text; using SGF.Extension; using SGF.Utils; namespace SGF.Network.FSPLite.Server { public class FSPManager { private long m_lastTicks = 0; private bool m_UseCustomEnterFrame; //=========================================================== private FSPParam m_param = new FSPParam(); private FSPGateway m_gateway; private MapList m_mapGame; private uint m_lastClearGameTime = 0; public void Init(int port) { Debuger.Log("port:{0}", port); m_gateway = new FSPGateway(); m_gateway.Init(port); m_param.port = m_gateway.Port; m_param.host = m_gateway.Host; m_mapGame = new MapList(); } public void Clean() { Debuger.Log(); m_mapGame.Clear(); } public void Dump() { m_gateway.Dump(); StringBuilder sb = new StringBuilder(); sb.AppendFormat("\nFSPParam:{0}", m_param.ToString("\t")); sb.AppendLine("\nGameList:"); var listGame = m_mapGame.AsDictionary(); foreach (var game in listGame) { sb.AppendFormat("\n\tGame {0}", game.Value.ToString("\t\t")); } Debuger.LogWarning(sb.ToString()); } //======================================================================= //设置FSP参数 public void SetFrameInterval(int serverFrameInterval, int clientFrameRateMultiple) //MS { Debuger.Log("serverFrameInterval:{0}, clientFrameRateMultiple:{1}", serverFrameInterval, clientFrameRateMultiple); m_param.serverFrameInterval = serverFrameInterval; m_param.clientFrameRateMultiple = clientFrameRateMultiple; } public void SetServerTimeout(int serverTimeout) { m_param.serverTimeout = serverTimeout; } public int GetFrameInterval() { return m_param.serverFrameInterval; } public FSPParam GetParam() { m_param.port = m_gateway.Port; m_param.host = m_gateway.Host; return m_param.Clone(); } //======================================================================= //管理Game单局 public FSPGame CreateGame(uint gameId, int authId) { Debuger.Log("gameId:{0}, auth:{1}", gameId, authId); FSPGame game = new FSPGame(); game.Create(gameId, authId); m_mapGame.Add(gameId, game); return game; } public void ReleaseGame(uint gameId) { Debuger.Log("gameId:{0}", gameId); FSPGame game = m_mapGame[gameId]; if (game != null) { game.Release(); m_mapGame.Remove(gameId); } } /// /// 创建一个玩家 /// /// /// /// SessionId public uint AddPlayer(uint gameId, uint playerId) { var game = m_mapGame[gameId]; var session = m_gateway.CreateSession(); game.AddPlayer(playerId, session); return session.id; } /// /// 创建一组玩家 /// /// /// /// SessionId列表 public List AddPlayer(uint gameId, List listPlayerId) { Debuger.Log("gameId:{0}, players:{1}", gameId, listPlayerId.ToListString()); var game = m_mapGame[gameId]; List listSid = new List(); for (int i = 0; i < listPlayerId.Count; i++) { var session = m_gateway.CreateSession(); game.AddPlayer(listPlayerId[i], session); listSid.Add(session.id); } return listSid; } //======================================================================= //时钟信号 public void Tick() { m_gateway.Tick(); //清除非激活的Game uint current = (uint)TimeUtils.GetTotalMillisecondsSince1970(); if (current - m_lastClearGameTime > FSPGame.ActiveTimeout * 1000 / 2) { m_lastClearGameTime = current; ClearNoActiveGame(); } long nowticks = DateTime.Now.Ticks; long interval = nowticks - m_lastTicks; //这里做了Fixbug long frameIntervalTicks = m_param.serverFrameInterval * 10000; if (interval > frameIntervalTicks) { m_lastTicks = nowticks - (nowticks % (frameIntervalTicks)); if (!m_UseCustomEnterFrame) { EnterFrame(); } } } public void EnterFrame() { if (m_gateway.IsRunning) { var listGame = m_mapGame.AsList(); for (int i = 0; i < listGame.Count; i++) { listGame[i].EnterFrame(); } } } private void ClearNoActiveGame() { var list = m_mapGame.AsList(); var dir = m_mapGame.AsDictionary(); int cnt = list.Count; for (int i = cnt - 1; i >= 0; i--) { var game = list[i]; if (game.IsGameEnd()) { list.RemoveAt(i); dir.Remove(game.id); } } } } } ================================================ FILE: SGFCore/Network/FSPLite/Server/FSPPlayer.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 帧同步模块 * Frame synchronization module * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Text; namespace SGF.Network.FSPLite.Server { public class FSPPlayer { private uint m_id; public uint id { get { return m_id; } } private bool m_hasAuthed = false; private FSPSession m_session; private Action m_RecvListener; //发送数据 private Queue m_FrameCache = null; private int m_LastAddFrameId = 0; private int m_authId = 0; public bool WaitForExit = false; //================================================================= public void Create(uint id, int authId, FSPSession session, Action listener) { Debuger.Log("id:{0}, authId:{1}, sid:{2}", id, authId, session.id); m_id = id; m_authId = authId; m_RecvListener = listener; m_session = session; m_session.SetReceiveListener(OnRecvFromSession); m_FrameCache = new Queue(); } public void Release() { Debuger.Log(); if (m_session != null) { m_session.SetReceiveListener(null); m_session.Active(false); m_session = null; } } public string ToString(string prefix = "") { StringBuilder sb = new StringBuilder(); sb.AppendFormat("[{0}] Auth:{1}, IsLose:{2}, EndPoint:{3}", m_id, HasAuthed, IsLose(), m_session.RemoteEndPoint); return sb.ToString(); } //==================================================================== //接收数据逻辑 private void OnRecvFromSession(FSPDataC2S data) { if (m_session.IsEndPointChanged) { m_session.IsEndPointChanged = false; m_hasAuthed = false; } if (m_RecvListener != null) { for (int i = 0; i < data.msgs.Count; i++) { m_RecvListener(this, data.msgs[i]); } } } //==================================================================== //发送相关逻辑 public void SendToClient(FSPFrame frame) { if (frame != null) { if (!m_FrameCache.Contains(frame)) { m_FrameCache.Enqueue(frame); } } while (m_FrameCache.Count > 0) { if (SendInternal(m_FrameCache.Peek())) { m_FrameCache.Dequeue(); } } } private bool SendInternal(FSPFrame frame) { if (frame.frameId != 0 && frame.frameId <= m_LastAddFrameId) { //已经Add过了 return true; } if (m_session != null) { if (m_session.Send(frame)) { m_LastAddFrameId = frame.frameId; return true; } } return false; } //==================================================================== //鉴权相关逻辑 public void SetAuth(int authId) { Debuger.Log(authId); //这里暂时不做真正的鉴权,只是让流程完整 m_hasAuthed = m_authId == authId; } public bool HasAuthed { get { return m_hasAuthed; } } //==================================================================== public void ClearRound() { Debuger.Log(); m_FrameCache.Clear(); m_LastAddFrameId = 0; } public bool IsLose() { return !m_session.IsActived(); } } } ================================================ FILE: SGFCore/Network/FSPLite/Server/FSPSession.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 帧同步模块 * Frame synchronization module * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Net; using System.Text; using SGF.Codec; using SGF.Network.Core; using SGF.Time; using SGF.Utils; namespace SGF.Network.FSPLite.Server { public class FSPSession { public static int ActiveTimeout = 300; private int m_lastActiveTime; private bool m_active = false; private uint m_id; private ushort m_ping; private Action m_sender; private Action m_listener; //RUDP private KCP m_Kcp; private SwitchQueue m_RecvBufQueue = new SwitchQueue(); private uint m_NextKcpUpdateTime = 0; private bool m_NeedKcpUpdateFlag = false; //数据发送 private byte[] m_SendBufferTemp = new byte[4096]; private FSPDataS2C m_TempSendData = new FSPDataS2C(); public FSPSession(uint sid, Action sender) { Debuger.Log(); m_id = sid; m_sender = sender; m_Kcp = new KCP(sid, HandleKcpSend); m_Kcp.NoDelay(1, 10, 2, 1); m_Kcp.WndSize(128, 128); m_active = true; } public string ToString(string prefix = "") { StringBuilder sb = new StringBuilder(); sb.AppendFormat("[{0}] Active:{1}, Ping:{2}, EndPoint:{3}", m_id, m_active, m_ping, RemoteEndPoint); return sb.ToString(); } public void SetReceiveListener(Action listener) { Debuger.Log(); m_listener = listener; } public uint id { get { return m_id; } } public ushort ping { get { return m_ping; } set { m_ping = value; } } public IPEndPoint RemoteEndPoint { get; private set; } public bool IsEndPointChanged { get; set; } public void Active(IPEndPoint remoteEndPoint) { m_lastActiveTime = (int)SGFTime.GetTimeSinceStartup(); m_active = true; if (this.RemoteEndPoint == null || !this.RemoteEndPoint.Equals(remoteEndPoint)) { IsEndPointChanged = true; this.RemoteEndPoint = remoteEndPoint; } } public void Active(bool value) { m_active = value; } public bool IsActived() { if (!m_active) { return false; } int dt = (int)SGFTime.GetTimeSinceStartup() - m_lastActiveTime; if (dt > ActiveTimeout) { m_active = false; } return m_active; } //================================================================== //发送数据 //================================================================== public bool Send(FSPFrame frame) { if (!IsActived()) { Debuger.LogWarning("Session已经不活跃了!"); return false; } m_TempSendData.frames.Clear(); m_TempSendData.frames.Add(frame); int len = PBSerializer.NSerialize(m_TempSendData, m_SendBufferTemp); return m_Kcp.Send(m_SendBufferTemp, len) == 0; } private void HandleKcpSend(byte[] buffer, int size) { m_sender(RemoteEndPoint, buffer, size); } //================================================================== //接收数据 //================================================================== public void DoReceiveInGateway(byte[] buffer, int size) { byte[] dst = new byte[size]; Buffer.BlockCopy(buffer, 0, dst, 0, size); m_RecvBufQueue.Push(dst); } private void DoReceiveInMain() { m_RecvBufQueue.Switch(); while (!m_RecvBufQueue.Empty()) { var recvBufferRaw = m_RecvBufQueue.Pop(); int ret = m_Kcp.Input(recvBufferRaw, recvBufferRaw.Length); //收到的不是一个正确的KCP包 if (ret < 0) { Debuger.LogError("收到不正确的KCP包!Ret:{0}", ret); return; } m_NeedKcpUpdateFlag = true; for (int size = m_Kcp.PeekSize(); size > 0; size = m_Kcp.PeekSize()) { var recvBuffer = new byte[size]; if (m_Kcp.Recv(recvBuffer) > 0) { if (m_listener != null) { FSPDataC2S data = PBSerializer.NDeserialize(recvBuffer); m_listener(data); } else { Debuger.LogError("找不到接收者!"); } } } } } public void Tick(uint currentTimeMS) { DoReceiveInMain(); uint current = currentTimeMS; if (m_NeedKcpUpdateFlag || current >= m_NextKcpUpdateTime) { m_Kcp.Update(current); m_NextKcpUpdateTime = m_Kcp.Check(current); m_NeedKcpUpdateFlag = false; } } } } ================================================ FILE: SGFCore/Network/General/Client/IConnection.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 连接接口定义(客户端) * Connection interface definition (client) * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Net; using SGF.Network.General.Proto; using SGF.SEvent; namespace SGF.Network.General.Client { public interface IConnection { /// /// 当收到数据时发出信号 /// 参数:字节数组,长度 /// Signal onReceive { get; } Signal onServerError{ get; } /// /// 清理整个连接,即反初始化 /// 它是统一管理的 /// void Clean(); /// /// 主动关闭连接 /// 对于Client来讲,有可能再次重连 /// 对于Server来讲,用于强制将 Client断线,然后由Gateway统一Clean /// void Close(); /// /// 连接操作 /// /// /// void Connect(string remoteIP, int remotePort); void Connect(IPEndPoint[] listRemoteEndPoints); /// /// SessionID /// uint Id { get; } /// /// 连接是否被激活 /// bool IsActived { get; } /// /// 连接的Ping值 /// ushort Ping { get; set; } /// /// 初始化成功后,可以获取本地EndPoint /// IPEndPoint LocalEndPoint { get; } /// /// 连接建立后,可以获取远端EndPoint /// IPEndPoint RemoteEndPoint { get; } /// /// 数据发送 /// 有可能是同步模式 /// 也可能是异步模式 /// /// /// bool Send(NetMessage msg); /// /// 无论是用IOCP,还是自己实现的IO模型 /// 都可能需要在网络线程与主线程之间【统一】同步数据 /// 当然只是可能,也不是必要的 /// 但是参照Apollo的设计,还是统一同步数据的 /// void Tick(); } } ================================================ FILE: SGFCore/Network/General/Client/KCPConnection.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 基于KCP的可靠UDP连接类(客户端) * KCP-based reliable UDP connection class (client) * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Net; using System.Net.Sockets; using System.Threading; using SGF.SEvent; using SGF.Network.Core; using SGF.Utils; using SGF.Network.General.Proto; using System.Collections.Generic; using SGF.Codec; namespace SGF.Network.General.Client { public class KcpConnection:IConnection, ILogTag { public string LOG_TAG { get; protected set; } //========================================================== //事件 //========================================================== public Signal onSendError { get; private set; } public Signal onReceiveError { get; private set; } public Signal onServerError { get; private set; } /// /// 当收到数据时发出信号 /// 参数:字节数组,长度 /// public Signal onReceive { get; private set; } //========================================================== //公共成员变量 //========================================================== public uint Id { get; protected set; } public IPEndPoint LocalEndPoint { get; private set; } public IPEndPoint RemoteEndPoint { get; private set; } public ushort Ping { get; set; } public bool IsActived { get { return Thread.VolatileRead(ref this.m_actived) == 1; } } private int m_actived = 0; //========================================================== //私有成员变量 //========================================================== private Socket m_socket; private Thread m_ThreadRecv; private byte[] m_RecvBufferTemp = new byte[4096]; private List m_listRemoteEndPoint; private int m_currRemoteEndPointIndex = -1; private int m_localPort; private bool m_waitReconnect = false; //KCP private KCP m_Kcp; private SwitchQueue m_RecvBufQueue = new SwitchQueue(); private uint m_NextKcpUpdateTime = 0; private bool m_NeedKcpUpdateFlag = false; //发送相关 private NetBufferWriter m_bufferSend; private NetBufferWriter m_bufferReceive = null; //========================================================== //构造函数 //========================================================== public KcpConnection(int localPort) { LOG_TAG = "KcpConnection[" + 0 + "," + localPort + "]"; this.Log("connId:{0}, localPort:{1}", 0, localPort); onReceive = new Signal(); onSendError = new Signal(); onReceiveError = new Signal(); onServerError = new Signal(); m_listRemoteEndPoint = new List(); m_currRemoteEndPointIndex = -1; m_bufferSend = new NetBufferWriter(new byte[0]); m_bufferReceive = new NetBufferWriter(new byte[NetDefine.ReceiveBufferMinSize]); m_localPort = localPort; } public void Clean() { this.Log(); onReceive.RemoveAllListeners(); onReceiveError.RemoveAllListeners(); onSendError.RemoveAllListeners(); onServerError.RemoveAllListeners(); Close(); } //====================================================================== //连接与断开连接 //====================================================================== public void Connect(string remoteIP, int remotePort) { this.Log("{0}:{1}", remoteIP, remotePort); IPAddress ipaddr = null; if (!IPAddress.TryParse(remoteIP, out ipaddr)) { this.LogError("无法解析为有效的IPAddress:{0}", remoteIP); return; } m_listRemoteEndPoint.Clear(); m_listRemoteEndPoint.Add(new IPEndPoint(ipaddr, remotePort)); m_currRemoteEndPointIndex = 0; ConnectInternal(m_listRemoteEndPoint[m_currRemoteEndPointIndex]); } public void Connect(IPEndPoint[] listRemoteEndPoint) { if (listRemoteEndPoint.Length == 0) { this.LogError("参数错误:listRemoteEndPoint.Length = 0"); return; } m_listRemoteEndPoint.Clear(); m_listRemoteEndPoint.AddRange(listRemoteEndPoint); m_currRemoteEndPointIndex = 0; ConnectInternal(m_listRemoteEndPoint[m_currRemoteEndPointIndex]); } public void Close() { this.Log(); this.m_actived = 0; if (m_Kcp != null) { m_Kcp.Dispose(); m_Kcp = null; } if (m_ThreadRecv != null) { m_ThreadRecv.Interrupt(); m_ThreadRecv = null; } if (m_socket != null) { try { m_socket.Shutdown(SocketShutdown.Both); } catch (Exception ex) { this.LogWarning(ex.Message); } m_socket.Close(); m_socket = null; } } private void TryReconnect() { Debuger.LogWarning(""); if (!IsActived) { m_currRemoteEndPointIndex++; m_currRemoteEndPointIndex = m_currRemoteEndPointIndex % m_listRemoteEndPoint.Count; ConnectInternal(m_listRemoteEndPoint[m_currRemoteEndPointIndex]); } else { this.LogWarning("当前连接还在,不能重连!"); } } private void ConnectInternal(IPEndPoint remoteEndPoint) { this.Log(); m_waitReconnect = false; var socket = new Socket(remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp); var localEndPoint = new IPEndPoint(IPAddress.Any, m_localPort); try { socket.Bind(localEndPoint); } catch (Exception exception) { this.LogWarning("指定的Port无法绑定:{0}", localEndPoint); } Active(socket, (IPEndPoint)remoteEndPoint); LOG_TAG = "KcpConnection[" + Id + "," + LocalEndPoint.Port + "]"; this.LogVerbose("连接成功!"); } public void Active(Socket socket, IPEndPoint remoteEndPoint) { if (Interlocked.CompareExchange(ref this.m_actived, 1, 0) == 0) { m_socket = socket; socket.ReceiveBufferSize = NetDefine.SocketBufferSize; socket.SendBufferSize = NetDefine.SocketBufferSize; RemoteEndPoint = (IPEndPoint)remoteEndPoint; LocalEndPoint = (IPEndPoint)socket.LocalEndPoint; ResetKcp(); m_ThreadRecv = new Thread(Thread_Recv) { IsBackground = true }; m_ThreadRecv.Start(); } } private void ResetKcp() { m_Kcp = new KCP(0, HandleKcpSend); m_Kcp.NoDelay(1, 10, 2, 1); m_Kcp.WndSize(128, 128); } //====================================================================== //发送数据 //====================================================================== public bool Send(NetMessage msg) { //主线程 this.LogVerbose(); msg.head.sid = Id; m_bufferSend.Attach(new byte[msg.Length], 0); msg.Serialize(m_bufferSend); var bytes = m_bufferSend.GetBytes(); var len = m_bufferSend.Length; return m_Kcp.Send(bytes, len) > 0; } private void HandleKcpSend(byte[] bytes, int len) { //主线程 m_hasSocketException = false; m_socket.SendTo(bytes, 0, len, SocketFlags.None, RemoteEndPoint); } //====================================================================== //接收数据 //====================================================================== protected void DoReceiveInThread() { //子线程 this.LogVerbose(); bool result = false; try { EndPoint remotePoint = IPUtils.GetIPEndPointAny(AddressFamily.InterNetwork, 0); int cnt = m_socket.ReceiveFrom(m_RecvBufferTemp, m_RecvBufferTemp.Length, SocketFlags.None, ref remotePoint); if (cnt > 0) { if (!RemoteEndPoint.Equals(remotePoint)) { Debuger.LogVerbose("收到非目标服务器的数据!"); return; } m_bufferReceive.Attach(m_RecvBufferTemp, cnt); byte[] m_32b = new byte[4]; m_bufferReceive.ReadBytes(m_32b, 0, 4); uint sid = BitConverter.ToUInt32(m_32b, 0); if(sid == 0) { //Session过期了 HandleServerError((int)NetErrorCode.SessionExpire); return; } byte[] dst = new byte[cnt]; Buffer.BlockCopy(m_RecvBufferTemp, 0, dst, 0, cnt); m_RecvBufQueue.Push(dst); } } catch (Exception ex) { this.LogWarning("接收数据出错:{0}", ex.Message); onReceiveError.InvokeSafe(this, (int)NetErrorCode.UnkownError, ex.Message); } } private void DoReceiveInMain() { //主线程 m_RecvBufQueue.Switch(); while (!m_RecvBufQueue.Empty()) { var recvBufferRaw = m_RecvBufQueue.Pop(); int ret = m_Kcp.Input(recvBufferRaw, recvBufferRaw.Length); //收到的不是一个正确的KCP包 if (ret < 0) { Debuger.LogError("收到不正确的KCP包!Ret:{0}", ret); return; } m_NeedKcpUpdateFlag = true; for (int size = m_Kcp.PeekSize(); size > 0; size = m_Kcp.PeekSize()) { var recvBuffer = new byte[size]; if (m_Kcp.Recv(recvBuffer) > 0) { NetMessage msg = new NetMessage(); msg.Deserialize(recvBuffer, size); if (msg.head.sid == 0) { var errmsg = PBSerializer.NDeserialize(msg.content); this.LogWarning("服务器返回错误:{0},{1}", errmsg.code, errmsg.info); HandleServerError(errmsg.code); onServerError.InvokeSafe(this, errmsg.code, errmsg.info); } else { //更新SessionId if (Id != msg.head.sid) { Id = msg.head.sid; LOG_TAG = "KcpConnection[" + Id + "," + m_localPort + "]"; this.LogWarning("SessionId发生变化:{0}", Id); } onReceive.InvokeSafe(msg); } } } } } private void HandleServerError(int errcode) { if (errcode == (int)NetErrorCode.SessionExpire) { Id = 0; LOG_TAG = "KcpConnection[" + Id + "," + m_localPort + "]"; this.LogWarning("Session过期!"); } onServerError.InvokeSafe(this, (int)NetErrorCode.UnkownError, ""); } //================================================================================= //接收线程 //================================================================================= private bool m_hasSocketException = false; private void Thread_Recv() { while (IsActived) { try { DoReceiveInThread(); if (m_hasSocketException) { m_hasSocketException = false; Debuger.LogWarning("连接异常已经恢复"); } } catch (SocketException se) { if (!m_hasSocketException) { m_hasSocketException = true; } Debuger.LogWarning("SocketErrorCode:{0}, {1}", se.SocketErrorCode, se.Message); Thread.Sleep(1); } catch (Exception e) { Debuger.LogWarning(e.Message + "\n" + e.StackTrace); Thread.Sleep(1); } } Debuger.LogWarning("End!"); } public void Tick() { if (IsActived) { DoReceiveInMain(); uint current = (uint) TimeUtils.GetTotalMillisecondsSince1970(); if (m_NeedKcpUpdateFlag || current >= m_NextKcpUpdateTime) { if (m_Kcp != null) { m_Kcp.Update(current); m_NextKcpUpdateTime = m_Kcp.Check(current); m_NeedKcpUpdateFlag = false; } } } else { if (m_waitReconnect) { TryReconnect(); } } } } } ================================================ FILE: SGFCore/Network/General/Client/NetManager.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 网络模块管理器(客户端) * Network Module Manager (Client) * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Net; using System.Reflection; using System.Text; using SGF.Codec; using SGF.Network.Core; using SGF.Network.Core.RPCLite; using SGF.Network.General.Proto; using SGF.SEvent; using SGF.Time; using SGF.Utils; namespace SGF.Network.General.Client { public class NetManager { public Signal onDisconnected { get; private set; } public Signal onConnectFailed { get; private set; } private IConnection m_conn; private uint m_token; private RPCManager m_rpc; public void Init(ConnectionType connType, int localPort = 0) { Debuger.Log("connType:{0}, localPort:{1}", connType, localPort); if (connType == ConnectionType.TCP) { var conn = new TcpConnection(localPort, null, 3); m_conn = conn; conn.onDisconnected.AddListener(OnDisconnected); conn.onConnectError.AddListener(OnConnectError); } else if (connType == ConnectionType.UDP) { m_conn = new UdpConnection(localPort, null); } else if(connType == ConnectionType.RUDP) { m_conn = new KcpConnection(localPort); } else { throw new ArgumentException("未实现该连接类型:" + connType); } onDisconnected = new Signal(); onConnectFailed = new Signal(); m_rpc = new RPCManager(m_conn); m_rpc.Init(); } public RPCManager Rpc { get { return m_rpc; } } public void Clean() { Debuger.Log(); if (m_conn != null) { m_conn.Clean(); m_conn = null; } if (m_rpc != null) { m_rpc.Clean(); m_rpc = null; } m_listNtfListener.Clear(); m_listRspListener.Clear(); } private void OnDisconnected(IConnection conn) { onDisconnected.Invoke(); } private void OnConnectError(IConnection conn, int code) { if(code == (int)NetErrorCode.ReconnectFailed) { onConnectFailed.Invoke(); } } public void Dump() { StringBuilder sb = new StringBuilder(); foreach (var pair in m_listNtfListener) { ListenerHelper helper = pair.Value; sb.AppendFormat("\t\n", pair.Key, helper.TMsg.Name, helper.onMsgMethod.DeclaringType.Name, helper.onMsgMethod.Name); } Debuger.LogWarning("\nNotify Listeners ({0}):\n{1}", m_listNtfListener.Count, sb); sb.Length = 0; var dic = m_listRspListener.AsDictionary(); foreach (var pair in dic) { ListenerHelper helper = pair.Value; sb.AppendFormat("\t\n", pair.Key, helper.TMsg.Name, helper.onMsgMethod.DeclaringType.Name, helper.onMsgMethod.Name); } Debuger.LogWarning("\nRespond Listeners ({0}):\n{1}", m_listRspListener.Count, sb); m_rpc.Dump(); } public void SetToken(uint token) { Debuger.Log(token); m_token = token; m_rpc.SetToken(token); } public void Connect(string ip, int port) { Debuger.Log("ip:{0}, port:{1}", ip, port); if (m_conn.IsActived) { Debuger.Log("旧的连接还在,先关闭旧的连接"); m_conn.Close(); } m_conn.Connect(ip, port); m_conn.onReceive.AddListener(OnReceive); } public void Connect(IPEndPoint[] listEndPoints) { if (m_conn.IsActived) { Debuger.Log("旧的连接还在,先关闭旧的连接"); m_conn.Close(); } m_conn.Connect(listEndPoints); m_conn.onReceive.AddListener(OnReceive); } public bool IsConnected { get { return m_conn.IsActived; } } public void Close() { Debuger.Log(); m_conn.Close(); } public void Tick() { m_conn.Tick(); CheckTimeout(); } private void OnReceive(NetMessage msg) { if (msg.head.cmd == 0) { RPCMessage rpcmsg = PBSerializer.NDeserialize(msg.content); m_rpc.OnReceive(rpcmsg); } else { HandlePBMessage(msg); } } //======================================================================== //传统的协议(Protobuf)处理方式 //======================================================================== class ListenerHelper { public uint cmd; public uint index; public Type TMsg; public Delegate onMsg0; public Delegate onMsg1; public Delegate onErr; public float timeout; public float timestamp; public MethodInfo onMsgMethod { get { var onMsg_ = onMsg0 != null ? onMsg0 : (onMsg1 != null ? onMsg1 : null); return onMsg_.Method; } } } static class MessageIndexGenerator { private static uint m_lastIndex; public static uint NewIndex() { return ++m_lastIndex; } } private DictionarySafe m_listNtfListener = new DictionarySafe(); private MapList m_listRspListener = new MapList(); /// /// 发送数据 /// /// /// /// /// /// /// /// 返回唯一的发送Index public uint Send(uint cmd, object req, Action onRsp, float timeout = 30, Action onErr = null) { Debuger.LogVerbose("cmd:{0}, timeout:{1}", cmd, timeout); uint index = MessageIndexGenerator.NewIndex(); ListenerHelper helper = new ListenerHelper() { cmd = cmd, index = index, TMsg = typeof(TRsp), onErr = onErr, onMsg0 = onRsp, timeout = timeout, timestamp = SGFTime.GetTimeSinceStartup() }; m_listRspListener.Add(index, helper); NetMessage msg = new NetMessage(); msg.head.index = index; msg.head.cmd = cmd; msg.head.token = m_token; msg.content = PBSerializer.NSerialize(req); msg.head.dataSize = (uint)msg.content.Length; m_conn.Send(msg); return index; } public void Send(uint cmd, TReq req) { Debuger.LogVerbose("cmd:{0}", cmd); NetMessage msg = new NetMessage(); msg.head.index = 0; msg.head.cmd = cmd; msg.head.token = m_token; msg.content = PBSerializer.NSerialize(req); msg.head.dataSize = (uint)msg.content.Length; m_conn.Send(msg); } public void Send(ProtocolHead head, uint cmd, TMsg msg) { Debuger.LogVerbose("cmd:{0}", cmd); NetMessage msgobj = new NetMessage(); msgobj.head = head; msgobj.head.cmd = cmd; msgobj.head.token = m_token; msgobj.content = PBSerializer.NSerialize(msg); msgobj.head.dataSize = (uint)msgobj.content.Length; m_conn.Send(msgobj); } public void AddListener(uint cmd, Action onNtf) { Debuger.Log("cmd:{0}, listener:{1}.{2}", cmd, onNtf.Method.DeclaringType.Name, onNtf.Method.Name); ListenerHelper helper = new ListenerHelper() { TMsg = typeof(TNtf), onMsg1 = onNtf }; m_listNtfListener.Add(cmd, helper); } public void RemoveListener(uint cmd) { Debuger.Log("cmd:{0}", cmd); m_listNtfListener.Remove(cmd); } private void HandlePBMessage(NetMessage msg) { Debuger.LogVerbose("msg.head:{0}", msg.head); if (msg.head.index == 0) { var helper = m_listNtfListener[msg.head.cmd]; if (helper != null) { object obj = null; try { obj = PBSerializer.NDeserialize(msg.content, helper.TMsg); } catch (Exception e) { Debuger.LogError("MsgName:{0}, msg.head:{0}", helper.TMsg.Name, msg.head); Debuger.LogError("DeserializeError:" + e.Message); } if (obj != null) { try { helper.onMsg1.DynamicInvoke(msg.head, obj); } catch (Exception e) { Debuger.LogError("MsgName:{0}, msg.head:{0}", helper.TMsg.Name, msg.head); Debuger.LogError("BusinessError:" + e.Message + "\n" + e.StackTrace); } } else { Debuger.LogError("协议格式错误! cmd:{0}", msg.head.cmd); } } else { Debuger.LogError("未找到对应的监听者! cmd:{0}", msg.head.cmd); } } else { var helper = m_listRspListener[msg.head.index]; if (helper != null) { m_listRspListener.Remove(msg.head.index); object obj = PBSerializer.NDeserialize(msg.content, helper.TMsg); if (obj != null) { helper.onMsg0.DynamicInvoke(msg.head.index, obj); } else { Debuger.LogError("协议格式错误! cmd:{0}, index:{0}", msg.head.cmd, msg.head.index); } } else { Debuger.LogError("未找到对应的监听者! cmd:{0}, index:{0}", msg.head.cmd, msg.head.index); } } } private float m_lastCheckTimeoutStamp = 0; private void CheckTimeout() { float curTime = SGFTime.GetTimeSinceStartup(); if (curTime - m_lastCheckTimeoutStamp >= 5) { m_lastCheckTimeoutStamp = curTime; var list = m_listRspListener.ToArray(); for (int i = 0; i < list.Length; i++) { var helper = list[i]; float dt = curTime - helper.timestamp; if (dt >= helper.timeout && helper.timeout > 0) { m_listRspListener.Remove(helper.index); if (helper.onErr != null) { helper.onErr.DynamicInvoke(NetErrorCode.Timeout); } Debuger.LogWarning("cmd:{0} Is Timeout!", helper.cmd); } } } } } } ================================================ FILE: SGFCore/Network/General/Client/RPCManager.cs ================================================ using SGF.Codec; using SGF.Network.Core.RPCLite; using SGF.Network.General.Proto; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; namespace SGF.Network.General.Client { public class RPCManager:RPCManagerBase { private IConnection m_conn; private uint m_token; public RPCManager(IConnection conn) { m_conn = conn; } public void OnReceive(RPCMessage msg) { HandleRPCMessage(msg); } public void SetToken(uint token) { Debuger.Log(token); m_token = token; } //======================================================================== //RPC的协议处理方式 //======================================================================== private string m_currInvokingName; private void HandleRPCMessage(RPCMessage rpcmsg) { Debuger.LogVerbose("Connection[{0}]-> {1}({2})", m_conn.Id, rpcmsg.name, rpcmsg.args); var helper = GetMethodHelper(rpcmsg.name); if (helper != null) { object[] args = rpcmsg.args; var raw_args = rpcmsg.raw_args; var paramInfo = helper.method.GetParameters(); if (raw_args.Count == paramInfo.Length) { for (int i = 0; i < raw_args.Count; i++) { if (raw_args[i].type == RPCArgType.PBObject) { var type = paramInfo[i].ParameterType; object arg = PBSerializer.NDeserialize(raw_args[i].raw_value, type); args[i] = arg; } } m_currInvokingName = rpcmsg.name; try { helper.method.Invoke(helper.listener, BindingFlags.NonPublic, null, args, null); } catch (Exception e) { Debuger.LogError("RPC调用出错:{0}\n{1}", e.Message, e.StackTrace); } m_currInvokingName = null; } else { Debuger.LogWarning("参数数量不一致!"); } } else { Debuger.LogWarning("RPC不存在!"); } } public void Invoke(string name, params object[] args) { Debuger.LogVerbose("->Connection[{0}] {1}({2})", m_conn.Id, name, args); RPCMessage rpcmsg = new RPCMessage(); rpcmsg.name = name; rpcmsg.args = args; byte[] buffer = PBSerializer.NSerialize(rpcmsg); NetMessage msg = new NetMessage(); msg.head = new ProtocolHead(); msg.head.token = m_token; msg.head.dataSize = (uint)buffer.Length; msg.content = buffer; m_conn.Send(msg); } public void Return(params object[] args) { if (m_conn != null) { var name = "On" + m_currInvokingName; Debuger.Log("->Connection[{0}] {1}({2})", m_conn.Id, name, args); RPCMessage rpcmsg = new RPCMessage(); rpcmsg.name = name; rpcmsg.args = args; byte[] buffer = PBSerializer.NSerialize(rpcmsg); NetMessage msg = new NetMessage(); msg.head = new ProtocolHead(); msg.head.token = m_token; msg.head.dataSize = (uint)buffer.Length; msg.content = buffer; m_conn.Send(msg); } } } } ================================================ FILE: SGFCore/Network/General/Client/TcpConnection.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Threading; using SGF.Network.Core; using SGF.Network.General.Proto; using SGF.SEvent; namespace SGF.Network.General.Client { public class TcpConnection:TcpConnectionBase, IConnection { //========================================================== //事件 //========================================================== public Signal onConnecting { get; private set; } public Signal onConnectSuccess { get; private set; } public Signal onConnectError { get; private set; } public Signal onDisconnected { get; private set; } public Signal onSendError { get; private set; } public Signal onSendSuccess { get; private set; } public Signal onReceiveError{ get; private set; } public Signal onServerError { get; private set; } /// /// 当收到数据时发出信号 /// 参数:字节数组,长度 /// public Signal onReceive { get; private set; } //========================================================== //私有成员变量 //========================================================== private List m_listRemoteEndPoint; private int m_currRemoteEndPointIndex = -1; private int m_localPort; private int m_maxReconnCnt = 0; private int m_curReconnIndex = 0; //========================================================== //构造函数 //========================================================== public TcpConnection(int localPort, SocketAsyncEventArgsPool pool, int maxReconnCnt = 0):base(pool) { LOG_TAG = "TcpConnection[" + 0 + "," + localPort + "]"; this.Log("connId:{0}, localPort:{1}, maxReconnCnt", 0, localPort, maxReconnCnt); m_maxReconnCnt = maxReconnCnt; onReceive = new Signal(); onConnectSuccess = new Signal(); onConnectError = new Signal(); onDisconnected = new Signal(); onSendSuccess = new Signal(); onSendError = new Signal(); onConnecting = new Signal(); onReceiveError = new Signal(); onServerError = new Signal(); m_listRemoteEndPoint = new List(); m_currRemoteEndPointIndex = -1; m_localPort = localPort; } public override void Clean() { base.Clean(); onReceive.RemoveAllListeners(); onConnectSuccess.RemoveAllListeners(); onConnectError.RemoveAllListeners(); onDisconnected.RemoveAllListeners(); onSendSuccess.RemoveAllListeners(); onSendError.RemoveAllListeners(); onConnecting.RemoveAllListeners(); onReceiveError.RemoveAllListeners(); onServerError.RemoveAllListeners(); m_listRemoteEndPoint.Clear(); GC.SuppressFinalize(this); } //====================================================================== //连接与断开连接 //====================================================================== /// /// 连接 /// /// /// public void Connect(string remoteIP, int remotePort) { this.Log("{0}:{1}", remoteIP, remotePort); IPAddress ipaddr = null; if (!IPAddress.TryParse(remoteIP, out ipaddr)) { this.LogError("无法解析为有效的IPAddress:{0}", remoteIP); return; } m_listRemoteEndPoint.Clear(); m_listRemoteEndPoint.Add(new IPEndPoint(ipaddr, remotePort)); m_currRemoteEndPointIndex = 0; ConnectInternal(m_listRemoteEndPoint[m_currRemoteEndPointIndex]); } public void Connect(IPEndPoint[] listRemoteEndPoint) { if (listRemoteEndPoint.Length == 0) { this.LogError("参数错误:listRemoteEndPoint.Length = 0"); return; } m_listRemoteEndPoint.Clear(); m_listRemoteEndPoint.AddRange(listRemoteEndPoint); m_currRemoteEndPointIndex = 0; ConnectInternal(m_listRemoteEndPoint[m_currRemoteEndPointIndex]); } private void TryReconnect() { this.Log(); if (!IsActived) { if (m_maxReconnCnt == 0 || m_curReconnIndex < m_maxReconnCnt) { m_curReconnIndex++; if (m_listRemoteEndPoint.Count > 0) { m_currRemoteEndPointIndex++; m_currRemoteEndPointIndex = m_currRemoteEndPointIndex % m_listRemoteEndPoint.Count; ConnectInternal(m_listRemoteEndPoint[m_currRemoteEndPointIndex]); } } else { onConnectError.Invoke(this, (int)NetErrorCode.ReconnectFailed); } } else { this.LogWarning("当前连接还在,不能重连!"); } } private void ConnectInternal(IPEndPoint remoteEndPoint) { this.Log(); onConnecting.Invoke(this); var socket = new Socket(remoteEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); var localEndPoint = new IPEndPoint(IPAddress.Any, m_localPort); try { socket.Bind(localEndPoint); } catch (Exception exception) { this.LogWarning("指定的Port无法绑定:{0}", localEndPoint); } var e = new SocketAsyncEventArgs(); e.UserToken = socket; e.RemoteEndPoint = remoteEndPoint; e.Completed += OnConnectCompleted; bool result = false; try { result = socket.ConnectAsync(e); } catch (Exception ex) { this.LogWarning(ex.Message); } if (!result) { ThreadPool.QueueUserWorkItem(_ => OnConnectCompleted(null, e)); } } private void OnConnectCompleted(object sender, SocketAsyncEventArgs e) { this.Log(e.SocketError.ToString()); var socket = e.UserToken as Socket; var error = e.SocketError; e.UserToken = null; e.Completed -= OnConnectCompleted; e.Dispose(); if (error != SocketError.Success) { socket.Close(); this.LogWarning("连接失败:{0}", error); OnConnectError((int)error); } else { base.Active(socket); LOG_TAG = "TcpConnection[" + Id + "," + LocalEndPoint.Port + "]"; this.Log("连接成功!"); onConnectSuccess.Invoke(this); } } private void OnConnectError(int errcode) { this.LogWarning(errcode.ToString()); onConnectError.Invoke(this, errcode); ThreadPool.QueueUserWorkItem(_ => TryReconnect()); } protected override void OnDisconnected() { base.OnDisconnected(); onDisconnected.Invoke(this); } //====================================================================== //发送数据 //====================================================================== protected override void OnSendError(int errcode, string info) { this.LogWarning("{0}:{1}", errcode, info); onSendError.Invoke(this, errcode,info); } protected override void OnSendSuccess() { onSendSuccess.Invoke(this); } //====================================================================== //接收数据 //====================================================================== protected override void OnReceiveError(int errcode, string info) { this.LogWarning("{0}:{1}", errcode, info); onReceiveError.Invoke(this, errcode,info); } public void Tick() { var msg = base.Receive(); while (msg != null) { //更新SessionId if (Id != msg.head.sid) { Id = msg.head.sid; LOG_TAG = "TcpConnection[" + Id + "," + m_localPort + "]"; this.LogWarning("SessionId发生变化:{0}", Id); } onReceive.Invoke(msg); msg = base.Receive(); } } } } ================================================ FILE: SGFCore/Network/General/Client/UdpConnection.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 基于UDP的不可靠连接类(客户端) * UDP-based unreliable connection class (client) * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Threading; using SGF.Codec; using SGF.Network.Core; using SGF.Network.General.Proto; using SGF.SEvent; namespace SGF.Network.General.Client { public class UdpConnection: IConnection, ILogTag { public string LOG_TAG { get; protected set; } //========================================================== //事件 //========================================================== public Signal onSendError { get; private set; } public Signal onReceiveError { get; private set; } public Signal onServerError { get; private set; } /// /// 当收到数据时发出信号 /// 参数:字节数组,长度 /// public Signal onReceive { get; private set; } //========================================================== //公共成员变量 //========================================================== public uint Id { get; protected set; } public IPEndPoint LocalEndPoint { get; private set; } public IPEndPoint RemoteEndPoint { get; private set; } public ushort Ping { get; set; } public bool IsActived { get { return Thread.VolatileRead(ref this.m_actived) == 1; } } private int m_actived = 0; //========================================================== //私有成员变量 //========================================================== private Socket m_socket; private SocketAsyncEventArgsPool m_pool; private List m_listRemoteEndPoint; private int m_currRemoteEndPointIndex = -1; private int m_localPort; //发送相关 private SocketAsyncEventArgs m_saeSend = null; private NetPacket m_currSendingPacket = null; private Queue m_queueSend; private NetBufferWriter m_bufferSend; private int m_sending = 0; //接收相关 private SocketAsyncEventArgs m_saeReceive = null; private Queue m_queueReceive; private NetBufferWriter m_bufferReceive; //========================================================== //构造函数 //========================================================== public UdpConnection(int localPort, SocketAsyncEventArgsPool pool) { LOG_TAG = "UdpConnection[" + 0 + "," + localPort + "]"; this.Log("connId:{0}, localPort:{1}", 0, localPort); onReceive = new Signal(); onSendError = new Signal(); onReceiveError = new Signal(); onServerError = new Signal(); m_listRemoteEndPoint = new List(); m_currRemoteEndPointIndex = -1; m_pool = new SocketAsyncEventArgsPool(NetDefine.PacketBufferSize, 0); m_queueSend = new Queue(); m_bufferSend = new NetBufferWriter(new byte[0]); m_queueReceive = new Queue(); m_bufferReceive = new NetBufferWriter(new byte[NetDefine.ReceiveBufferMinSize]); m_localPort = localPort; } public void Clean() { this.Log(); onReceive.RemoveAllListeners(); onReceiveError.RemoveAllListeners(); onSendError.RemoveAllListeners(); onServerError.RemoveAllListeners(); Close(); } private void CleanSend() { this.Log(); m_currSendingPacket = null; if (m_saeSend != null) { m_saeSend.Completed -= OnSendCompleted; m_pool.Release(m_saeSend); m_saeSend = null; } } private void CleanReceive() { this.Log(); if (m_saeReceive != null) { m_saeReceive.Completed -= OnReceiveCompleted; m_pool.Release(m_saeReceive); m_saeReceive = null; } } //====================================================================== //连接与断开连接 //====================================================================== /// /// 连接 /// /// /// public void Connect(string remoteIP, int remotePort) { this.Log("{0}:{1}", remoteIP, remotePort); IPAddress ipaddr = null; if (!IPAddress.TryParse(remoteIP, out ipaddr)) { this.LogError("无法解析为有效的IPAddress:{0}", remoteIP); return; } m_listRemoteEndPoint.Clear(); m_listRemoteEndPoint.Add(new IPEndPoint(ipaddr, remotePort)); m_currRemoteEndPointIndex = 0; ConnectInternal(m_listRemoteEndPoint[m_currRemoteEndPointIndex]); } public void Connect(IPEndPoint[] listRemoteEndPoint) { if (listRemoteEndPoint.Length == 0) { this.LogError("参数错误:listRemoteEndPoint.Length = 0"); return; } m_listRemoteEndPoint.Clear(); m_listRemoteEndPoint.AddRange(listRemoteEndPoint); m_currRemoteEndPointIndex = 0; ConnectInternal(m_listRemoteEndPoint[m_currRemoteEndPointIndex]); } public void Close() { this.Log(); this.m_actived = 0; if (m_socket != null) { try { m_socket.Shutdown(SocketShutdown.Both); } catch (Exception ex) { this.LogWarning(ex.Message); } m_socket.Close(); m_socket = null; } CleanSend(); CleanReceive(); } private void TryReconnect() { this.Log(); if (!IsActived) { m_currRemoteEndPointIndex++; m_currRemoteEndPointIndex = m_currRemoteEndPointIndex % m_listRemoteEndPoint.Count; ConnectInternal(m_listRemoteEndPoint[m_currRemoteEndPointIndex]); } else { this.LogWarning("当前连接还在,不能重连!"); } } private void ConnectInternal(IPEndPoint remoteEndPoint) { this.Log(); var socket = new Socket(remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp); var localEndPoint = new IPEndPoint(IPAddress.Any, m_localPort); try { socket.Bind(localEndPoint); } catch (Exception exception) { this.LogWarning("指定的Port无法绑定:{0}", localEndPoint); } var e = new SocketAsyncEventArgs(); e.UserToken = socket; e.RemoteEndPoint = remoteEndPoint; e.Completed += OnConnectCompleted; ThreadPool.QueueUserWorkItem(_ => OnConnectCompleted(null, e)); } private void OnConnectCompleted(object sender, SocketAsyncEventArgs e) { this.LogVerbose(e.SocketError.ToString()); var socket = e.UserToken as Socket; var error = e.SocketError; e.UserToken = null; e.Completed -= OnConnectCompleted; e.Dispose(); Active(socket, (IPEndPoint)e.RemoteEndPoint); LOG_TAG = "UdpConnection[" + Id + "," + LocalEndPoint.Port + "]"; this.LogVerbose("连接成功!"); } public void Active(Socket socket, IPEndPoint remoteEndPoint) { if (Interlocked.CompareExchange(ref this.m_actived, 1, 0) == 0) { m_socket = socket; socket.ReceiveBufferSize = NetDefine.SocketBufferSize; socket.SendBufferSize = NetDefine.SocketBufferSize; RemoteEndPoint = (IPEndPoint)remoteEndPoint; LocalEndPoint = (IPEndPoint)socket.LocalEndPoint; m_saeSend = m_pool.Acquire(); m_saeSend.Completed += OnSendCompleted; m_saeSend.RemoteEndPoint = remoteEndPoint; m_saeReceive = m_pool.Acquire(); m_saeReceive.Completed += OnReceiveCompleted; m_saeReceive.RemoteEndPoint = remoteEndPoint; BeginSend(); BeginReceive(); } } //====================================================================== //发送数据 //====================================================================== public bool Send(NetMessage msg) { this.LogVerbose(); msg.head.sid = Id; m_bufferSend.Attach(new byte[msg.Length], 0); msg.Serialize(m_bufferSend); NetPacket packet = new NetPacket(m_bufferSend.GetBytes()); lock (m_queueSend) { m_queueSend.Enqueue(packet); } if (m_sending == 0 && m_actived == 1) { if (m_currSendingPacket == null) { lock (m_queueSend) { if (m_queueSend.Count > 0) { m_currSendingPacket = m_queueSend.Dequeue(); SendInternal(m_saeSend); } } } } return true; } protected void BeginSend() { TrySendNext(); } private void TrySendNext() { this.LogVerbose(); if (m_sending == 0) { if (m_currSendingPacket == null) { lock (m_queueSend) { if (m_queueSend.Count > 0) { m_currSendingPacket = m_queueSend.Dequeue(); SendInternal(m_saeSend); } } } } } private void SendInternal(SocketAsyncEventArgs e) { this.LogVerbose(e.SocketError.ToString()); m_sending = 1; var packet = m_currSendingPacket; var length = Math.Min(packet.Bytes.Length - packet.SentSize, e.Buffer.Length); var result = false; try { Buffer.BlockCopy(packet.Bytes, packet.SentSize, e.Buffer, 0, length); e.SetBuffer(0, length); result = m_socket.SendToAsync(e); } catch (Exception ex) { this.LogWarning("发送数据出错:{0}", ex.Message); onSendError.InvokeSafe(this, (int)NetErrorCode.UnkownError,ex.Message); } if (!result) { ThreadPool.QueueUserWorkItem(_ => OnSendCompleted(this, e)); } } private void OnSendCompleted(object sender, SocketAsyncEventArgs e) { this.LogVerbose(e.SocketError.ToString()); if (e.SocketError != SocketError.Success) { this.LogWarning("发送失败!{0}", e.SocketError); onSendError.InvokeSafe(this,(int)NetErrorCode.UnkownError, e.SocketError.ToString()); //继续发下一个Packet m_currSendingPacket = null; m_sending = 0; TrySendNext(); return; } var packed = m_currSendingPacket; packed.SentSize += e.BytesTransferred; //将PackedBufferSize的Buffer发送完 if (e.Offset + e.BytesTransferred < e.Count) { var result = true; try { e.SetBuffer(e.Offset + e.BytesTransferred, e.Count - e.BytesTransferred - e.Offset); result = m_socket.SendAsync(e); } catch (Exception ex) { this.LogWarning("发送数据出错:{0}", ex.Message); onSendError.InvokeSafe(this, (int)NetErrorCode.UnkownError, ex.Message); } if (!result) { ThreadPool.QueueUserWorkItem(_ => OnSendCompleted(this, e)); } } else { if (!packed.IsSent) { //继续发当前Packet的下一个分组 SendInternal(e); } else { //一个Packet发送完成 m_currSendingPacket = null; m_sending = 0; //继续发下一个Packet TrySendNext(); } } } //====================================================================== //接收数据 //====================================================================== protected void BeginReceive() { ReceiveInternal(); } private void ReceiveInternal() { this.LogVerbose(); bool result = false; try { result = m_socket.ReceiveFromAsync(m_saeReceive); } catch (Exception ex) { this.LogWarning("接收数据出错:{0}", ex.Message); onReceiveError.InvokeSafe(this, (int) NetErrorCode.UnkownError, ex.Message); } if (!result) { ThreadPool.QueueUserWorkItem(_ => OnReceiveCompleted(this, m_saeReceive)); } } private void OnReceiveCompleted(object sender, SocketAsyncEventArgs e) { this.LogVerbose(e.SocketError.ToString()); if (e.SocketError != SocketError.Success) { this.LogWarning("接收出错!{0}", e.SocketError); onReceiveError.InvokeSafe(this, (int)NetErrorCode.SocketError, e.SocketError.ToString()); ReceiveInternal(); return; } if (e.BytesTransferred < 1) { this.LogWarning("接收出错!{0}", e.SocketError); onReceiveError.InvokeSafe(this, (int)NetErrorCode.SocketError, e.SocketError.ToString()); ReceiveInternal(); return; } m_bufferReceive.Attach(e.Buffer, e.BytesTransferred); NetMessage msg = new NetMessage(); if (msg.Deserialize(m_bufferReceive)) { lock (m_queueReceive) { m_queueReceive.Enqueue(msg); } } else { this.LogError("反序列化失败!"); onReceiveError.InvokeSafe(this, (int)NetErrorCode.DeserializeError, "反序列化失败"); } ReceiveInternal(); } //=================================================================== /// /// 主线程读取数据 /// /// private NetMessage Receive() { NetMessage msg = null; lock (m_queueReceive) { if (m_queueReceive.Count > 0) { msg = m_queueReceive.Dequeue(); return msg; } } return null; } public void Tick() { var msg = Receive(); while (msg != null) { if (msg.head.sid == 0) { var errmsg = PBSerializer.NDeserialize(msg.content); this.LogWarning("服务器返回错误:{0},{1}", errmsg.code, errmsg.info); HandleServerError(errmsg.code); onServerError.InvokeSafe(this, errmsg.code, errmsg.info); } else { //更新SessionId if (Id != msg.head.sid) { Id = msg.head.sid; LOG_TAG = "UdpConnection[" + Id + "," + m_localPort + "]"; this.LogWarning("SessionId发生变化:{0}", Id); } onReceive.InvokeSafe(msg); } msg = Receive(); } } private void HandleServerError(int errcode) { if (errcode == (int) NetErrorCode.SessionExpire) { Id = 0; LOG_TAG = "UdpConnection[" + Id + "," + m_localPort + "]"; this.LogWarning("Session过期!"); } onServerError.InvokeSafe(this, (int)NetErrorCode.UnkownError, ""); } } } ================================================ FILE: SGFCore/Network/General/ConnectionType.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ namespace SGF.Network.General { public enum ConnectionType { TCP = 1, UDP = 2, RUDP = 3, FSP = 4 } } ================================================ FILE: SGFCore/Network/General/NetDefine.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ namespace SGF.Network.General { public class NetDefine { /// /// 收包数据的最小Buffer大小 /// 实际收包时,如果Buffer里的数据没有人读取,会自动扩容 /// public static int ReceiveBufferMinSize = 1024; /// /// Socket的Buffer大小 /// public static int SocketBufferSize = 8192; /// /// 底层分包的Buffer大小 /// public static int PacketBufferSize = 8192; } } ================================================ FILE: SGFCore/Network/General/NetPacket.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; namespace SGF.Network.General { public class NetPacket { internal int SentSize; public readonly byte[] Bytes; public NetPacket(byte[] bytes) { if (bytes == null) throw new ArgumentNullException("bytes"); this.Bytes = bytes; } public bool IsSent { get { return this.SentSize == Bytes.Length; } } } } ================================================ FILE: SGFCore/Network/General/Proto/NetErrorProto.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using ProtoBuf; namespace SGF.Network.General.Proto { [ProtoContract] public class NetErrorMessage { [ProtoMember(1)] public int code; [ProtoMember(2)] public string info; } [ProtoContract] public class ReturnCode { public static ReturnCode Success = new ReturnCode(); public static ReturnCode UnkownError = new ReturnCode(1, "UnkownError"); public ReturnCode(int code, string info) { this.code = code; this.info = info; } public ReturnCode() { this.code = 0; this.info = ""; } [ProtoMember(1)] public int code = 0; [ProtoMember(2)] public string info = ""; public override string ToString() { return string.Format("ErrCode:{0}, Info:{1}", code, info); } } } ================================================ FILE: SGFCore/Network/General/Proto/NetMessage.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 封装了网络消息 * Encapsulates network messages * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using SGF.Network.Core; namespace SGF.Network.General.Proto { public class NetMessage { private static NetBuffer DefaultWriter = new NetBuffer(4096); private static NetBuffer DefaultReader = new NetBuffer(4096); public ProtocolHead head = new ProtocolHead(); public byte[] content; public uint Length{get { return head.dataSize + ProtocolHead.Length; } } public bool Deserialize(NetBuffer buffer) { if (head.Deserialize(buffer)) { if (buffer.BytesAvailable >= head.dataSize) { content = new byte[head.dataSize]; buffer.ReadBytes(content, 0, (int)head.dataSize); return true; } } return false; } public NetBuffer Serialize(NetBuffer buffer) { head.Serialize(buffer); buffer.WriteBytes(content, 0, (int)head.dataSize); return buffer; } public bool Deserialize(byte[] buffer, int size) { lock (DefaultReader) { DefaultReader.Attach(buffer, size); return Deserialize(DefaultReader); } } public int Serialize(out byte[] tempBuffer) { lock (DefaultWriter) { DefaultWriter.Clear(); this.Serialize(DefaultWriter); tempBuffer = DefaultWriter.GetBytes(); return DefaultWriter.Length; } } } } ================================================ FILE: SGFCore/Network/General/Proto/ProfilerTestProto.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using ProtoBuf; namespace SGF.Network.General.Proto { internal class ProfilerTestProto { public class ProtoCmd { public static uint LoginReq = 1; public static uint LoginRsp = 2; public static uint HeartBeatReq = 3; public static uint HeartBeatRsp = 4; } [ProtoContract] public class LoginReq { [ProtoMember(1)] public uint id; [ProtoMember(2)] public string name; } [ProtoContract] public class LoginRsp { [ProtoMember(1)] public int ret; [ProtoMember(2)] public string name; } [ProtoContract] public class HeartBeatReq { [ProtoMember(1)] public ushort ping; [ProtoMember(2)] public uint timestamp; } [ProtoContract] public class HeartBeatRsp { [ProtoMember(1)] public int ret; [ProtoMember(2)] public uint timestamp; } } } ================================================ FILE: SGFCore/Network/General/Proto/ProtocolHead.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 封装了协议头 * Encapsulates protocol head * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using SGF.Network.Core; namespace SGF.Network.General.Proto { public class ProtocolHead { public const int Length = 44; public uint sid = 0; public uint token = 0; public uint cmd = 0; public uint index = 0; public ulong player = 0; public int zone = 0; public ulong runner = 0; public uint dataSize = 0; public uint checksum = 0; public override string ToString() { return string.Format("sid:{0}, token:{1}, cmd:{2}, index:{3}, player:{4}, zone:{5}, runner:{6}, dataSize:{7}, checksum:{8}", sid, token, cmd, index, player,zone,runner, dataSize, checksum); } public bool Deserialize(NetBuffer buffer) { if (buffer.BytesAvailable >= Length) { ProtocolHead head = this; head.sid = buffer.ReadUInt(); head.token = buffer.ReadUInt(); head.cmd = buffer.ReadUInt(); head.index = buffer.ReadUInt(); head.player = buffer.ReadULong(); head.zone = buffer.ReadInt(); head.runner = buffer.ReadULong(); head.dataSize = buffer.ReadUInt(); head.checksum = buffer.ReadUInt(); return true; } return false; } public NetBuffer Serialize(NetBuffer buffer) { buffer.WriteUInt(sid); buffer.WriteUInt(token); buffer.WriteUInt(cmd); buffer.WriteUInt(index); buffer.WriteULong(player); buffer.WriteInt(zone); buffer.WriteULong(runner); buffer.WriteUInt(dataSize); buffer.WriteUInt(checksum); return buffer; } } } ================================================ FILE: SGFCore/Network/General/Server/IGateway.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ namespace SGF.Network.General.Server { public interface IGateway { void Clean(); void Dump(); void Tick(); } } ================================================ FILE: SGFCore/Network/General/Server/ISession.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 会话接口定义(客户端) * Session interface definition (client) * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System.Net; using SGF.Network.General.Proto; namespace SGF.Network.General.Server { public interface ISessionListener { void OnReceive(ISession session, NetMessage msg); void OnDisconnected(ISession session); } public interface ISession { uint AuthToken { get; set; } /// /// SessionID /// uint Id { get; } /// /// 连接是否被激活 /// bool IsActived { get; } /// /// 连接的Ping值 /// ushort Ping { get; set; } /// /// 初始化成功后,可以获取本地EndPoint /// IPEndPoint LocalEndPoint { get; } /// /// 连接建立后,可以获取远端EndPoint /// IPEndPoint RemoteEndPoint { get; } /// /// 数据发送 /// 有可能是同步模式 /// 也可能是异步模式 /// /// /// bool Send(NetMessage msg); void Tick(int currentMS); } } ================================================ FILE: SGFCore/Network/General/Server/KCPGateway.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 网关类(服务器) * Gateway class (Server) * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using SGF.Network.Core; using SGF.Utils; namespace SGF.Network.General.Server { public class KcpGateway : IGateway, ILogTag { public string LOG_TAG { get; protected set; } public IPEndPoint LocalEndPoint { get; private set; } public static int SessionActiveTimeout = 5; private MapList m_mapSession; private bool m_IsRunning = false; private ISessionListener m_listener; private int m_port; private Socket m_socket = null; private NetBufferWriter m_bufferReceive = null; private Thread m_ThreadRecv; private byte[] m_RecvBufferTemp = new byte[4096]; private bool m_waitStart = false; public KcpGateway(int port, ISessionListener listener) { LOG_TAG = "KcpGateway<" + port + ">"; this.Log("port:{0}", port); m_bufferReceive = new NetBufferWriter(); m_port = port; m_listener = listener; m_mapSession = new MapList(); Start(); } public void Clean() { this.Log(); m_mapSession.Clear(); Close(); } public void Dump() { StringBuilder sb = new StringBuilder(); var dic = m_mapSession.AsDictionary(); foreach (var pair in dic) { ISession session = pair.Value; sb.AppendLine("\t" + session.ToString()); } this.LogWarning("\nGateway Sessions ({0}):\n{1}", m_mapSession.Count, sb); } private static long m_lastSessionId = 0; private uint NewSessionID() { return (uint)Interlocked.Increment(ref m_lastSessionId); } private void Start() { this.LogWarning(""); m_IsRunning = true; if (m_socket == null) { m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); m_socket.Bind(new IPEndPoint(IPAddress.Any, m_port)); LocalEndPoint = m_socket.LocalEndPoint as IPEndPoint; m_port = LocalEndPoint.Port; ; m_ThreadRecv = new Thread(Thread_Recv) { IsBackground = true }; m_ThreadRecv.Start(); } } private void DoReceiveInThread() { EndPoint remotePoint = IPUtils.GetIPEndPointAny(AddressFamily.InterNetwork, 0); int cnt = m_socket.ReceiveFrom(m_RecvBufferTemp, m_RecvBufferTemp.Length, SocketFlags.None, ref remotePoint); if (cnt > 0) { m_bufferReceive.Attach(m_RecvBufferTemp, cnt); byte[] m_32b = new byte[4]; m_bufferReceive.ReadBytes(m_32b, 0, 4); uint sid = BitConverter.ToUInt32(m_32b, 0); lock (m_mapSession) { KcpSession session = null; if (sid == 0) { //来自Client的第1个包,只能是鉴权包 session = new KcpSession(NewSessionID(), m_listener); m_mapSession.Add(session.Id, session); } else { session = m_mapSession[sid]; } if (session != null) { session.Active(m_socket, remotePoint as IPEndPoint); session.DoReceiveInGateway(m_RecvBufferTemp, cnt); } else { this.LogWarning("无效的包! sid:{0}", sid); //需要返回给客户端,Session无效了,直接返回一个Sid为0的包 //当客户端收到包好,会抛出Session过期事件 //因为正常情况下,客户端收到的Session肯定不为0 m_socket.SendTo(new byte[4], remotePoint); } } } } private void Close() { this.LogWarning(""); m_IsRunning = false; if (m_ThreadRecv != null) { m_ThreadRecv.Interrupt(); m_ThreadRecv = null; } if (m_socket != null) { try { m_socket.Shutdown(SocketShutdown.Both); } catch (Exception e) { this.LogWarning(e.Message + e.StackTrace); } m_socket.Close(); m_socket = null; } } //================================================================================= //接收线程 //================================================================================= private bool m_hasSocketException = false; private void Thread_Recv() { Debuger.LogWarning("Begin ......"); while (m_IsRunning) { try { DoReceiveInThread(); if (m_hasSocketException) { m_hasSocketException = false; Debuger.LogWarning("连接异常已经恢复"); } } catch (SocketException se) { if (!m_hasSocketException) { m_hasSocketException = true; } Debuger.LogWarning("SocketErrorCode:{0}, {1}", se.SocketErrorCode,se.Message); Thread.Sleep(1); } catch (Exception e) { Debuger.LogWarning(e.Message + "\n" + e.StackTrace); Thread.Sleep(1); } } Debuger.LogWarning("End!"); } private int m_lastClearSessionTime = 0; public void Tick() { if (m_IsRunning) { lock (m_mapSession) { int current = (int)TimeUtils.GetTotalMillisecondsSince1970(); if (current - m_lastClearSessionTime > SessionActiveTimeout * 1000 / 2) { m_lastClearSessionTime = current; ClearNoActiveSession(); } var list = m_mapSession.AsList(); int cnt = list.Count; for (int i = 0; i < cnt; i++) { list[i].Tick(current); } } } } private void ClearNoActiveSession() { var list = m_mapSession.AsList(); var dir = m_mapSession.AsDictionary(); int cnt = list.Count; for (int i = cnt - 1; i >= 0; i--) { var session = list[i]; if (!session.IsActived) { list.RemoveAt(i); dir.Remove(session.Id); session.Clean(); } } } } } ================================================ FILE: SGFCore/Network/General/Server/KCPSession.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 基于KCP的可靠UDP会话类(服务器) * KCP-based reliable UDP session class (server) * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using SGF.Network.Core; using SGF.Network.General.Proto; using SGF.SEvent; using SGF.Time; namespace SGF.Network.General.Server { public class KcpSession:ISession, ILogTag { public string LOG_TAG { get; protected set; } //========================================================== //事件 //========================================================== public Signal onSendError { get; private set; } public Signal onReceiveError { get; private set; } //========================================================== //公共成员变量 //========================================================== public uint AuthToken { get; set; } public uint Id { get; protected set; } public IPEndPoint LocalEndPoint { get; private set; } public IPEndPoint RemoteEndPoint { get; private set; } public ushort Ping { get; set; } public bool IsActived { get { return Thread.VolatileRead(ref this.m_actived) == 1; } } private int m_actived = 0; //========================================================== //私有成员变量 //========================================================== private Socket m_socket; private ISessionListener m_listener; private NetBufferWriter m_bufferSend; private Queue m_queueReceive; //KCP private KCP m_Kcp; private SwitchQueue m_RecvBufQueue = new SwitchQueue(); private uint m_NextKcpUpdateTime = 0; private bool m_NeedKcpUpdateFlag = false; public KcpSession(uint sid, ISessionListener listener) { LOG_TAG = "KcpSession[" + sid + "]"; this.Log(); onSendError = new Signal(); onReceiveError = new Signal(); m_bufferSend = new NetBufferWriter(new byte[0]); m_queueReceive = new Queue(); this.Id = sid; m_listener = listener; } public string ToString(string prefix = "") { return "KcpSession[" + Id + "," + RemoteEndPoint.Port + "]"; } public virtual void Clean() { this.Log(); m_socket = null; m_actived = 0; } //====================================================================== //连接与断开连接相关 //====================================================================== public void Active(Socket socket, IPEndPoint remoteEndPoint) { RemoteEndPoint = (IPEndPoint)remoteEndPoint; if (Interlocked.CompareExchange(ref this.m_actived, 1, 0) == 0) { m_socket = socket; LocalEndPoint = (IPEndPoint)socket.LocalEndPoint; m_Kcp = new KCP(Id, HandleKcpSend); m_Kcp.NoDelay(1, 10, 2, 1); m_Kcp.WndSize(128, 128); } } //====================================================================== //发送数据 //====================================================================== public bool Send(NetMessage msg) { this.Log(); if (!IsActived) { Debuger.LogWarning("Session已经不活跃了!"); return false; } msg.head.sid = Id; m_bufferSend.Attach(new byte[msg.Length], 0); msg.Serialize(m_bufferSend); var bytes = m_bufferSend.GetBytes(); var len = m_bufferSend.Length; return m_Kcp.Send(bytes, len) == 0; } private void HandleKcpSend(byte[] bytes, int len) { m_socket.SendTo(bytes, 0, len, SocketFlags.None, RemoteEndPoint); } //====================================================================== //接收数据 //====================================================================== public void DoReceiveInGateway(byte[] buffer, int size) { byte[] dst = new byte[size]; Buffer.BlockCopy(buffer, 0, dst, 0, size); m_RecvBufQueue.Push(dst); } private void DoReceiveInMain() { m_RecvBufQueue.Switch(); while (!m_RecvBufQueue.Empty()) { var recvBufferRaw = m_RecvBufQueue.Pop(); int ret = m_Kcp.Input(recvBufferRaw, recvBufferRaw.Length); //收到的不是一个正确的KCP包 if (ret < 0) { Debuger.LogError("收到不正确的KCP包!Ret:{0}", ret); return; } m_NeedKcpUpdateFlag = true; for (int size = m_Kcp.PeekSize(); size > 0; size = m_Kcp.PeekSize()) { var recvBuffer = new byte[size]; if (m_Kcp.Recv(recvBuffer) > 0) { NetMessage msg = new NetMessage(); msg.Deserialize(recvBuffer, size); m_listener.OnReceive(this, msg); } } } } public void Tick(int currentTimeMS) { DoReceiveInMain(); uint current = (uint)currentTimeMS; if (m_NeedKcpUpdateFlag || current >= m_NextKcpUpdateTime) { m_Kcp.Update(current); m_NextKcpUpdateTime = m_Kcp.Check(current); m_NeedKcpUpdateFlag = false; } } } } ================================================ FILE: SGFCore/Network/General/Server/NetManager.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 网络模块管理器(服务器) * Network Module Manager (Server) * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Reflection; using System.Text; using SGF.Codec; using SGF.Network.Core.RPCLite; using SGF.Network.General.Proto; using SGF.SEvent; using SGF.Utils; namespace SGF.Network.General.Server { public class NetManager : ISessionListener { public Signal onDisconnected { get; private set; } private IGateway m_gateway; private uint m_authCmd = 0; private RPCManager m_rpc; public void Init(ConnectionType connType, int port) { Debuger.Log("connType:{0}, port:{1}", connType, port); if (connType == ConnectionType.TCP) { m_gateway = new TcpGateway(port, this); } else if (connType == ConnectionType.UDP) { m_gateway = new UdpGateway(port, this); } else if (connType == ConnectionType.RUDP) { m_gateway = new KcpGateway(port, this); } else { throw new ArgumentException("未实现该连接类型:" + connType); } onDisconnected = new Signal(); m_rpc = new RPCManager(); m_rpc.Init(); } public RPCManager Rpc { get { return m_rpc; } } public void Clean() { Debuger.Log(); if (m_gateway != null) { m_gateway.Clean(); m_gateway = null; } if (m_rpc != null) { m_rpc.Clean(); m_rpc = null; } m_listMsgListener.Clear(); onDisconnected.RemoveAllListeners(); } public void Dump() { m_gateway.Dump(); StringBuilder sb = new StringBuilder(); foreach (var pair in m_listMsgListener) { ListenerHelper helper = pair.Value; sb.AppendFormat("\t\n", pair.Key, helper.TMsg.Name, helper.onMsgMethod.DeclaringType.Name, helper.onMsgMethod.Name); } Debuger.LogWarning("\nNet Listeners ({0}):\n{1}", m_listMsgListener.Count, sb); m_rpc.Dump(); } public void SetAuthCmd(uint cmd) { m_authCmd = cmd; } public void Tick() { m_gateway.Tick(); } public void OnReceive(ISession session, NetMessage msg) { if (session.AuthToken == msg.head.token) { if (msg.head.cmd == 0) { RPCMessage rpcmsg = PBSerializer.NDeserialize(msg.content); m_rpc.OnReceive(session, rpcmsg); } else { HandlePBMessage(session, msg); } } else { Debuger.LogWarning("收到消息的Token与Session的Token不一致!session.token:{0}, msg.token:{1}", session.AuthToken, msg.head.token); if (m_authCmd == 0 || msg.head.cmd == m_authCmd) { HandlePBMessage(session, msg); } else { Debuger.LogWarning("收到未鉴权的消息! cmd:{0}", msg.head.cmd); } } } public void OnDisconnected(ISession session) { onDisconnected.Invoke(session); } //======================================================================== //传统的协议处理方式 //======================================================================== class ListenerHelper { public Type TMsg; public Delegate onMsg0; public Delegate onMsg1; public MethodInfo onMsgMethod { get { var onMsg = onMsg0 != null ? onMsg0 : (onMsg1 != null ? onMsg1 : null); return onMsg.Method; } } } private DictionarySafe m_listMsgListener = new DictionarySafe(); private void HandlePBMessage(ISession session, NetMessage msg) { Debuger.LogVerbose("msg.head:{0}", msg.head); var helper = m_listMsgListener[msg.head.cmd]; if (helper != null) { object obj = null; try { obj = PBSerializer.NDeserialize(msg.content, helper.TMsg); } catch (Exception e) { Debuger.LogError("MsgName:{0}, msg.head:{0}", helper.TMsg.Name, msg.head); Debuger.LogError("DeserializeError:" + e.Message); } if (obj != null) { try { if (helper.onMsg0 != null) { helper.onMsg0.DynamicInvoke(session, msg.head.index, obj); } else if (helper.onMsg1 != null) { helper.onMsg1.DynamicInvoke(session, msg.head, obj); } } catch (Exception e) { Debuger.LogError("MsgName:{0}, msg.head:{0}", helper.TMsg.Name, msg.head); Debuger.LogError("BusinessError:" + e.Message + "\n" + e.StackTrace); } } } else { Debuger.LogWarning("未找到对应的监听者! cmd:{0}", msg.head.cmd); } } public void Send(ISession session, ProtocolHead head, uint cmd, TMsg msg) { Debuger.LogVerbose("index:{0}, cmd:{1}", head.index, cmd); NetMessage msgobj = new NetMessage(); msgobj.head = head; msgobj.head.cmd = cmd; msgobj.head.token = session.AuthToken; msgobj.content = PBSerializer.NSerialize(msg); msgobj.head.dataSize = (uint)msgobj.content.Length; session.Send(msgobj); } public void AddListener(uint cmd, Action onMsg) { Debuger.Log("cmd:{0}, listener:{1}.{2}", cmd, onMsg.Method.DeclaringType.Name, onMsg.Method.Name); ListenerHelper helper = new ListenerHelper() { TMsg = typeof(TMsg), onMsg0 = onMsg }; m_listMsgListener.Add(cmd, helper); } public void AddListener(uint cmd, Action onMsg) { Debuger.Log("cmd:{0}, listener:{1}.{2}", cmd, onMsg.Method.DeclaringType.Name, onMsg.Method.Name); ListenerHelper helper = new ListenerHelper() { TMsg = typeof(TMsg), onMsg1 = onMsg }; m_listMsgListener.Add(cmd, helper); } } } ================================================ FILE: SGFCore/Network/General/Server/RPCManager.cs ================================================ using SGF.Codec; using SGF.Extension; using SGF.Network.Core.RPCLite; using SGF.Network.General.Proto; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; namespace SGF.Network.General.Server { public class RPCManager:RPCManagerBase { public void OnReceive(ISession session, RPCMessage msg) { HandleRPCMessage(session, msg); } //======================================================================== //RPC的协议处理方式 //======================================================================== private ISession m_currInvokingSession; private string m_currInvokingName; public void HandleRPCMessage(ISession session, RPCMessage rpcmsg) { RPCMethodHelper helper = GetMethodHelper(rpcmsg.name); if (helper != null) { object[] args = new object[rpcmsg.raw_args.Count + 1]; var raw_args = rpcmsg.raw_args; var paramInfo = helper.method.GetParameters(); args[0] = session; if (args.Length == paramInfo.Length) { for (int i = 0; i < raw_args.Count; i++) { if (raw_args[i].type == RPCArgType.PBObject) { args[i + 1] = PBSerializer.NDeserialize(raw_args[i].raw_value, paramInfo[i + 1].ParameterType); } else { args[i + 1] = raw_args[i].value; } } m_currInvokingName = rpcmsg.name; m_currInvokingSession = session; try { helper.method.Invoke(helper.listener, BindingFlags.NonPublic, null, args, null); } catch (Exception e) { Debuger.LogError("RPC调用出错:{0}\n{1}", e.Message, e.StackTrace); } m_currInvokingName = null; m_currInvokingSession = null; } else { Debuger.LogWarning("参数数量不一致:{0},{1}<->{2}", rpcmsg.name, args.Length, paramInfo.Length); } } else { Debuger.LogWarning("RPC不存在:{0}", rpcmsg.name); } } public void Return(params object[] args) { var name = "On" + m_currInvokingName; RPCMessage rpcmsg = new RPCMessage(); rpcmsg.name = name; rpcmsg.args = args; byte[] buffer = PBSerializer.NSerialize(rpcmsg); NetMessage msg = new NetMessage(); msg.head = new ProtocolHead(); msg.head.dataSize = (uint)buffer.Length; msg.content = buffer; m_currInvokingSession.Send(msg); } public void ReturnError(params object[] args) { var name = "On" + m_currInvokingName + "Error"; RPCMessage rpcmsg = new RPCMessage(); rpcmsg.name = name; rpcmsg.args = args; byte[] buffer = PBSerializer.NSerialize(rpcmsg); NetMessage msg = new NetMessage(); msg.head = new ProtocolHead(); msg.head.dataSize = (uint)buffer.Length; msg.content = buffer; m_currInvokingSession.Send(msg); } public void Invoke(ISession session, string name, params object[] args) { Debuger.LogVerbose("->Session[{0}] {1}({2})", session.Id, name, args.ToListString()); RPCMessage rpcmsg = new RPCMessage(); rpcmsg.name = name; rpcmsg.args = args; byte[] buffer = PBSerializer.NSerialize(rpcmsg); NetMessage msg = new NetMessage(); msg.head = new ProtocolHead(); msg.head.dataSize = (uint)buffer.Length; msg.content = buffer; session.Send(msg); } public void Invoke(ISession[] listSession, string name, params object[] args) { Debuger.Log("->Session {1}({2})", listSession.Length, name, args.ToListString()); RPCMessage rpcmsg = new RPCMessage(); rpcmsg.name = name; rpcmsg.args = args; byte[] buffer = PBSerializer.NSerialize(rpcmsg); NetMessage msg = new NetMessage(); msg.head = new ProtocolHead(); msg.head.dataSize = (uint)buffer.Length; msg.content = buffer; for (int i = 0; i < listSession.Length; i++) { listSession[i].Send(msg); } } } } ================================================ FILE: SGFCore/Network/General/Server/TcpGateway.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using SGF.Network.Core; using SGF.Utils; namespace SGF.Network.General.Server { public class TcpGateway:IGateway { public static int SessionActiveTimeout = 5; private MapList m_mapSession; private bool m_IsRunning = false; private ISessionListener m_listener; private int m_port; private bool m_waitReStart = false; private const int BACKLOG = 500; private Socket m_socket = null; private readonly SocketAsyncEventArgs m_saeAccept = null; private SocketAsyncEventArgsPool m_saePool; public TcpGateway(int port, ISessionListener listener) { Debuger.Log("port:{0}", port); m_saePool = new SocketAsyncEventArgsPool(NetDefine.PacketBufferSize, 10000); m_saeAccept = new SocketAsyncEventArgs(); m_saeAccept.Completed += OnAcceptCompleted; m_port = port; m_listener = listener; m_mapSession = new MapList(); Start(); } public void Clean() { Debuger.Log(); m_mapSession.Clear(); Close(); } public void Dump() { StringBuilder sb = new StringBuilder(); var dic = m_mapSession.AsDictionary(); var i = 0; foreach (var pair in dic) { i++; ISession session = pair.Value; sb.AppendLine("\t" + i + "."+ session.ToString()); } Debuger.LogWarning("\nGateway Sessions ({0}):\n{1}", m_mapSession.Count, sb); } private static long m_lastSessionId = 0; private uint NewSessionID() { return (uint)Interlocked.Increment(ref m_lastSessionId); } public void Start() { Debuger.LogWarning(""); m_waitReStart = false; m_IsRunning = true; if (m_socket == null) { m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); m_socket.Bind(new IPEndPoint(IPAddress.Any, m_port)); m_socket.Listen(BACKLOG); AcceptAsync(); } } private void AcceptAsync() { if (m_socket == null) { return; } bool result = true; try { result = m_socket.AcceptAsync(m_saeAccept); } catch (Exception ex) { Debuger.LogError(ex.Message); } if (!result) System.Threading.ThreadPool.QueueUserWorkItem(_ => OnAcceptCompleted(this, m_saeAccept)); } private void OnAcceptCompleted(object sender, SocketAsyncEventArgs e) { Socket acceptSocket = null; if (e.SocketError == SocketError.Success) { acceptSocket = e.AcceptSocket; } e.AcceptSocket = null; if (acceptSocket != null) { var sid = NewSessionID(); var session = new TcpSession(sid, m_saePool, m_listener); session.Active(acceptSocket); lock (m_mapSession) { m_mapSession.Add(session.Id, session); } } this.AcceptAsync(); } private void Close() { Debuger.LogWarning(""); m_IsRunning = false; if (m_socket != null) { try { m_socket.Shutdown(SocketShutdown.Both); } catch (Exception e) { Debuger.LogWarning(e.Message + e.StackTrace); } m_socket.Close(); m_socket = null; } } private void ReStart() { Debuger.LogWarning(""); Close(); m_waitReStart = true; } public ISession GetSession(long sid) { ISession session = null; lock (m_mapSession) { session = m_mapSession[sid]; } return session; } //================================================================================= //检查超时 //================================================================================= private int m_lastClearSessionTime = 0; public void Tick() { if (m_IsRunning) { lock (m_mapSession) { int current = (int)TimeUtils.GetTotalMillisecondsSince1970(); if (current - m_lastClearSessionTime > SessionActiveTimeout * 1000 / 2) { m_lastClearSessionTime = current; ClearNoActiveSession(); } var list = m_mapSession.AsList(); int cnt = list.Count; for (int i = 0; i < cnt; i++) { list[i].Tick(current); } } } else { if (m_waitReStart) { Start(); } } } private void ClearNoActiveSession() { var list = m_mapSession.AsList(); var dir = m_mapSession.AsDictionary(); int cnt = list.Count; for (int i = cnt - 1; i >= 0; i--) { var session = list[i]; if (!session.IsActived) { list.RemoveAt(i); dir.Remove(session.Id); session.Clean(); } } } } } ================================================ FILE: SGFCore/Network/General/Server/TcpSession.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using SGF.Network.Core; using SGF.SEvent; namespace SGF.Network.General.Server { public class TcpSession:TcpConnectionBase, ISession { //========================================================== //事件 //========================================================== public Signal onDisconnected { get; private set; } public Signal onSendError { get; private set; } public Signal onSendSuccess { get; private set; } public Signal onReceiveError { get; private set; } //========================================================== //公共成员变量 //========================================================== public uint AuthToken { get; set; } //========================================================== //私有成员变量 //========================================================== private ISessionListener m_listener; public TcpSession(uint sid, SocketAsyncEventArgsPool pool, ISessionListener listener):base(pool) { LOG_TAG = "TcpSession[" + sid + "]"; this.Log(); onDisconnected = new Signal(); onSendSuccess = new Signal(); onSendError = new Signal(); onReceiveError = new Signal(); this.Id = sid; m_listener = listener; } public override string ToString() { return "TcpSession[" + Id + "," + RemoteEndPoint.Port + "]"; } //====================================================================== //断开连接相关 //====================================================================== protected override void OnDisconnected() { base.OnDisconnected(); m_listener.OnDisconnected(this); onDisconnected.Invoke(this); } //====================================================================== //发送数据 //====================================================================== protected override void OnSendError(int errcode, string info) { this.LogWarning("{0}:{1}", errcode, info); onSendError.Invoke(this, errcode); } protected override void OnSendSuccess() { onSendSuccess.Invoke(this); } //====================================================================== //接收数据 //====================================================================== protected override void OnReceiveError(int errcode, string info) { this.LogWarning("{0}:{1}", errcode, info); onReceiveError.Invoke(this, errcode); } public void Tick(int currentMS) { var msg = base.Receive(); while (msg != null) { m_listener.OnReceive(this, msg); msg = base.Receive(); } } } } ================================================ FILE: SGFCore/Network/General/Server/UdpGateway.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 网关类(服务器) * Gateway class (Server) * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using SGF.Network.Core; using SGF.Network.General.Proto; using SGF.Utils; namespace SGF.Network.General.Server { public class UdpGateway:IGateway,ILogTag { public string LOG_TAG { get; protected set; } public IPEndPoint LocalEndPoint { get; private set; } public static int SessionActiveTimeout = 5; private MapList m_mapSession; private bool m_IsRunning = false; private ISessionListener m_listener; private int m_port; private Socket m_socket = null; private SocketAsyncEventArgs m_saeReceive = null; private NetBufferWriter m_bufferReceive = null; private SocketAsyncEventArgsPool m_pool; public UdpGateway(int port, ISessionListener listener) { LOG_TAG = "UdpGateway<" + port + ">"; this.Log("port:{0}", port); m_bufferReceive = new NetBufferWriter(); m_pool = new SocketAsyncEventArgsPool(NetDefine.PacketBufferSize, 10000); m_port = port; m_listener = listener; m_mapSession = new MapList(); Start(); } public void Clean() { this.Log(); m_mapSession.Clear(); Close(); } private void CleanReceive() { this.Log(); if (m_saeReceive != null) { m_saeReceive.Completed -= OnReceiveCompleted; m_pool.Release(m_saeReceive); m_saeReceive = null; } } public void Dump() { StringBuilder sb = new StringBuilder(); var dic = m_mapSession.AsDictionary(); var i = 0; foreach (var pair in dic) { i++; ISession session = pair.Value; sb.AppendLine("\t" + i + "." + session.ToString()); } Debuger.LogWarning("\nGateway Sessions ({0}):\n{1}", m_mapSession.Count, sb); } private static long m_lastSessionId = 0; private uint NewSessionID() { return (uint)Interlocked.Increment(ref m_lastSessionId); } public void Start() { this.LogWarning(""); m_IsRunning = true; if (m_socket == null) { m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); m_socket.Bind(new IPEndPoint(IPAddress.Any, m_port)); LocalEndPoint = m_socket.LocalEndPoint as IPEndPoint; m_port = LocalEndPoint.Port; ; m_saeReceive = m_pool.Acquire(); m_saeReceive.Completed += OnReceiveCompleted; m_saeReceive.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); ReceiveAsync(); } } private void ReceiveAsync() { if (m_socket == null) { return; } bool result = true; try { result = m_socket.ReceiveFromAsync(m_saeReceive); } catch (Exception ex) { Debuger.LogError(ex.Message); } if (!result) { System.Threading.ThreadPool.QueueUserWorkItem(_ => OnReceiveCompleted(this, m_saeReceive)); } } private void OnReceiveCompleted(object sender, SocketAsyncEventArgs e) { this.Log(e.SocketError.ToString()); if (e.SocketError != SocketError.Success) { this.LogWarning(e.SocketError.ToString()); } else { if (e.BytesTransferred == 0) { this.LogWarning("收到的数据长度为0"); } else { m_bufferReceive.Attach(e.Buffer, e.BytesTransferred); NetMessage msg = new NetMessage(); if (msg.Deserialize(m_bufferReceive)) { lock (m_mapSession) { UdpSession session = null; if (msg.head.sid == 0) { session = new UdpSession(NewSessionID(), m_pool, m_listener); m_mapSession.Add(session.Id, session); } else { session = m_mapSession[msg.head.sid]; if (session == null) { //对于UDP,可以重新分配SessionId session = new UdpSession(NewSessionID(), m_pool, m_listener); m_mapSession.Add(session.Id, session); } } if (session != null) { session.Active(m_socket, (IPEndPoint)e.RemoteEndPoint); session.DoReceiveInGateway(msg); } else { this.LogWarning("无效的包! sid:{0}", msg.head.sid); //需要返回给客户端,Session无效了 UdpSession.ReturnErrorMessage(m_socket, (IPEndPoint) e.RemoteEndPoint, NetErrorCode.SessionExpire, "Session Expired!"); } } } else { this.LogError("反序列化失败!"); } } } this.ReceiveAsync(); } private void Close() { this.LogWarning(""); m_IsRunning = false; if (m_socket != null) { try { m_socket.Shutdown(SocketShutdown.Both); } catch (Exception e) { this.LogWarning(e.Message + e.StackTrace); } m_socket.Close(); m_socket = null; } CleanReceive(); } //================================================================================= //检查超时 //================================================================================= private int m_lastClearSessionTime = 0; public void Tick() { if (m_IsRunning) { lock (m_mapSession) { int current = (int)TimeUtils.GetTotalMillisecondsSince1970(); if (current - m_lastClearSessionTime > SessionActiveTimeout * 1000 / 2) { m_lastClearSessionTime = current; ClearNoActiveSession(); } var list = m_mapSession.AsList(); int cnt = list.Count; for (int i = 0; i < cnt; i++) { list[i].Tick(current); } } } } private void ClearNoActiveSession() { var list = m_mapSession.AsList(); var dir = m_mapSession.AsDictionary(); int cnt = list.Count; for (int i = cnt - 1; i >= 0; i--) { var session = list[i]; if (!session.IsActived) { list.RemoveAt(i); dir.Remove(session.Id); session.Clean(); } } } } } ================================================ FILE: SGFCore/Network/General/Server/UdpSession.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Threading; using SGF.Codec; using SGF.Network.Core; using SGF.Network.General.Proto; using SGF.SEvent; namespace SGF.Network.General.Server { public class UdpSession:ISession, ILogTag { public string LOG_TAG { get; protected set; } //========================================================== //事件 //========================================================== public Signal onSendError { get; private set; } public Signal onReceiveError { get; private set; } //========================================================== //公共成员变量 //========================================================== public uint AuthToken { get; set; } public uint Id { get; protected set; } public IPEndPoint LocalEndPoint { get; private set; } public IPEndPoint RemoteEndPoint { get; private set; } public ushort Ping { get; set; } public bool IsActived{get { return Thread.VolatileRead(ref this.m_actived) == 1; }} private int m_actived = 0; //========================================================== //私有成员变量 //========================================================== private Socket m_socket; private SocketAsyncEventArgsPool m_pool; private ISessionListener m_listener; //发送相关 private SocketAsyncEventArgs m_saeSend = null; private NetPacket m_currSendingPacket = null; private Queue m_queueSend; private NetBufferWriter m_bufferSend; private int m_sending = 0; //接收相关 private Queue m_queueReceive; public UdpSession(uint sid, SocketAsyncEventArgsPool pool, ISessionListener listener) { LOG_TAG = "UdpSession[" + sid + "]"; this.Log(); onSendError = new Signal(); onReceiveError = new Signal(); m_pool = pool; m_queueSend = new Queue(); m_bufferSend = new NetBufferWriter(new byte[0]); m_queueReceive = new Queue(); this.Id = sid; m_listener = listener; } public override string ToString() { return "UdpSession[" + Id + "," + RemoteEndPoint.Port + "]"; } public virtual void Clean() { this.Log(); m_socket = null; m_actived = 0; CleanSend(); } private void CleanSend() { this.Log(); m_currSendingPacket = null; if (m_saeSend != null) { m_saeSend.Completed -= OnSendCompleted; m_pool.Release(m_saeSend); m_saeSend = null; } } //====================================================================== //连接与断开连接相关 //====================================================================== public void Active(Socket socket, IPEndPoint remoteEndPoint) { RemoteEndPoint = (IPEndPoint)remoteEndPoint; if (Interlocked.CompareExchange(ref this.m_actived, 1, 0) == 0) { m_socket = socket; LocalEndPoint = (IPEndPoint)socket.LocalEndPoint; m_saeSend = m_pool.Acquire(); m_saeSend.Completed += OnSendCompleted; m_saeSend.RemoteEndPoint = remoteEndPoint; BeginSend(); } } //====================================================================== //发送数据 //====================================================================== public bool Send(NetMessage msg) { this.Log(); msg.head.sid = Id; m_bufferSend.Attach(new byte[msg.Length], 0); msg.Serialize(m_bufferSend); NetPacket packet = new NetPacket(m_bufferSend.GetBytes()); lock (m_queueSend) { m_queueSend.Enqueue(packet); } if (m_sending == 0 && m_actived == 1) { if (m_currSendingPacket == null) { lock (m_queueSend) { if (m_queueSend.Count > 0) { m_currSendingPacket = m_queueSend.Dequeue(); SendInternal(m_saeSend); } } } } return true; } protected void BeginSend() { TrySendNext(); } private void TrySendNext() { this.Log(); if (m_sending == 0) { if (m_currSendingPacket == null) { lock (m_queueSend) { if (m_queueSend.Count > 0) { m_currSendingPacket = m_queueSend.Dequeue(); SendInternal(m_saeSend); } } } } } private void SendInternal(SocketAsyncEventArgs e) { this.Log(e.SocketError.ToString()); m_sending = 1; var packet = m_currSendingPacket; var length = Math.Min(packet.Bytes.Length - packet.SentSize, e.Buffer.Length); var result = false; try { Buffer.BlockCopy(packet.Bytes, packet.SentSize, e.Buffer, 0, length); e.SetBuffer(0, length); result = m_socket.SendToAsync(e); } catch (Exception ex) { this.LogWarning("发送数据出错:{0}", ex.Message); } if (!result) { ThreadPool.QueueUserWorkItem(_ => OnSendCompleted(this, e)); } } private void OnSendCompleted(object sender, SocketAsyncEventArgs e) { this.Log(e.SocketError.ToString()); if (e.SocketError != SocketError.Success) { this.LogWarning("发送数据出错:{0}", e.SocketError); onSendError.Invoke(this, (int)NetErrorCode.UnkownError); return; } var packed = m_currSendingPacket; packed.SentSize += e.BytesTransferred; //将PackedBufferSize的Buffer发送完 if (e.Offset + e.BytesTransferred < e.Count) { var result = true; try { e.SetBuffer(e.Offset + e.BytesTransferred, e.Count - e.BytesTransferred - e.Offset); result = m_socket.SendToAsync(e); } catch (Exception ex) { this.LogWarning("发送数据出错:{0}", ex.Message); } if (!result) { ThreadPool.QueueUserWorkItem(_ => OnSendCompleted(this, e)); } } else { if (!packed.IsSent) { //继续发当前Packet的下一个分组 SendInternal(e); } else { //一个Packet发送完成 m_currSendingPacket = null; m_sending = 0; //继续发下一个Packet TrySendNext(); } } } //====================================================================== //接收数据 //====================================================================== internal void DoReceiveInGateway(NetMessage msg) { lock (m_queueReceive) { m_queueReceive.Enqueue(msg); } } public NetMessage Receive() { NetMessage msg = null; lock (m_queueReceive) { if (m_queueReceive.Count > 0) { msg = m_queueReceive.Dequeue(); return msg; } } return null; } public void Tick(int currentMS) { var msg = Receive(); while (msg != null) { m_listener.OnReceive(this, msg); msg = Receive(); } } internal static void ReturnErrorMessage(Socket socket, IPEndPoint remoteEndPoint, NetErrorCode errcode, string errinfo = "") { NetErrorMessage msg = new NetErrorMessage(); msg.code = (int)errcode; msg.info = errinfo; NetMessage msgobj = new NetMessage(); msgobj.head.index = 0; msgobj.head.cmd = 0; msgobj.head.token = 0; msgobj.head.sid = 0; msgobj.content = PBSerializer.NSerialize(msg); msgobj.head.dataSize = (uint)msgobj.content.Length; NetBuffer bufferSend = new NetBuffer(new byte[msgobj.Length]); msgobj.Serialize(bufferSend); socket.SendTo(bufferSend.GetBytes(), remoteEndPoint); } } } ================================================ FILE: SGFCore/Network/General/TcpConnectionBase.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Threading; using SGF.Network.Core; using SGF.Network.General.Proto; namespace SGF.Network.General { public class TcpConnectionBase:ILogTag { public string LOG_TAG { get; protected set; } //========================================================== //公共成员变量 //========================================================== public uint Id { get; protected set; } public IPEndPoint LocalEndPoint { get; private set; } public IPEndPoint RemoteEndPoint { get; private set; } public bool IsActived { get { return Thread.VolatileRead(ref this.m_actived) == 1; } } private int m_actived = 0; public ushort Ping { get; set; } //========================================================== //私有成员变量 //========================================================== private Socket m_socket; private SocketAsyncEventArgsPool m_pool; //发送相关 private SocketAsyncEventArgs m_saeSend = null; private NetPacket m_currSendingPacket = null; private Queue m_queueSend; private NetBufferWriter m_bufferSend; private int m_sending = 0; //接收相关 private SocketAsyncEventArgs m_saeReceive = null; private Queue m_queueReceive; private NetBufferWriter m_bufferReceive; //========================================================== //构造与清理 //========================================================== public TcpConnectionBase(SocketAsyncEventArgsPool pool = null) { LOG_TAG = "TcpConnectionBase"; m_pool = pool; if (m_pool == null) { m_pool = new SocketAsyncEventArgsPool(NetDefine.PacketBufferSize, 0); } m_queueSend = new Queue(); m_bufferSend = new NetBufferWriter(new byte[0]); m_queueReceive = new Queue(); m_bufferReceive = new NetBufferWriter(new byte[NetDefine.ReceiveBufferMinSize]); } public virtual void Clean() { this.Log(); m_actived = 0; Close(); } private void CleanSend() { this.Log(); m_currSendingPacket = null; if (m_saeSend != null) { m_saeSend.Completed -= OnSendCompleted; m_pool.Release(m_saeSend); m_saeSend = null; } } private void CleanReceive() { this.Log(); if (m_saeReceive != null) { m_saeReceive.Completed -= OnReceiveCompleted; m_pool.Release(m_saeReceive); m_saeReceive = null; } } //====================================================================== //连接(对于Client和Server,以及UDP和TCP,连接的逻辑不同)与断开连接 //====================================================================== public void Active(Socket socket) { if (m_actived == 0) { m_socket = socket; socket.NoDelay = true; socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true); socket.ReceiveBufferSize = NetDefine.SocketBufferSize; socket.SendBufferSize = NetDefine.SocketBufferSize; RemoteEndPoint = (IPEndPoint)socket.RemoteEndPoint; LocalEndPoint = (IPEndPoint)socket.LocalEndPoint; m_saeSend = m_pool.Acquire(); m_saeSend.Completed += OnSendCompleted; m_saeReceive = m_pool.Acquire(); m_saeReceive.Completed += OnReceiveCompleted; m_actived = 1; BeginSend(); BeginReceive(); } } public void Close() { this.Log(); if (m_socket != null) { try { m_socket.Shutdown(SocketShutdown.Both); } catch (Exception ex) { this.LogWarning(ex.Message); } m_socket.Close(); m_socket = null; } CleanSend(); CleanReceive(); if (Interlocked.CompareExchange(ref this.m_actived, 0, 1) == 1) { Disconnect(); } } private void Disconnect() { this.Log(); m_actived = 0; m_sending = 0; CleanSend(); CleanReceive(); var e = new SocketAsyncEventArgs(); e.Completed += OnDisconnectCompleted; var result = false; try { m_socket.Shutdown(SocketShutdown.Both); result = m_socket.DisconnectAsync(e); } catch (Exception ex) { //this.LogError(ex.Message); } if (!result) { ThreadPool.QueueUserWorkItem(_ => OnDisconnectCompleted(this, e)); } } private void OnDisconnectCompleted(object sender, SocketAsyncEventArgs e) { this.Log(e.SocketError.ToString()); e.Completed -= OnDisconnectCompleted; e.Dispose(); try { m_socket.Close(); } catch (Exception ex) { } OnDisconnected(); } protected virtual void OnDisconnected() { } //====================================================================== //发送数据 //====================================================================== public bool Send(NetMessage msg) { this.LogVerbose(); msg.head.sid = Id; m_bufferSend.Attach(new byte[msg.Length], 0); msg.Serialize(m_bufferSend); NetPacket packet = new NetPacket(m_bufferSend.GetBytes()); lock (m_queueSend) { m_queueSend.Enqueue(packet); } if (m_sending == 0 && m_actived == 1) { lock (m_queueSend) { if (m_currSendingPacket == null) { if (m_queueSend.Count > 0) { m_currSendingPacket = m_queueSend.Dequeue(); SendInternal(m_saeSend); } } } } return true; } protected void BeginSend() { TrySendNext(); } private void TrySendNext() { this.LogVerbose(); if (m_sending == 0) { lock (m_queueSend) { if (m_currSendingPacket == null) { if (m_queueSend.Count > 0) { m_currSendingPacket = m_queueSend.Dequeue(); SendInternal(m_saeSend); } } } } } private void SendInternal(SocketAsyncEventArgs e) { this.LogVerbose("{0}",e.SocketError); m_sending = 1; var packet = m_currSendingPacket; var length = Math.Min(packet.Bytes.Length - packet.SentSize, e.Buffer.Length); var result = false; try { Buffer.BlockCopy(packet.Bytes, packet.SentSize, e.Buffer, 0, length); e.SetBuffer(0, length); result = m_socket.SendAsync(e); } catch (Exception ex) { this.LogError("发送数据出错:{0}", ex.Message); } if (!result) { ThreadPool.QueueUserWorkItem(_ => OnSendCompleted(this, e)); } } private void OnSendCompleted(object sender, SocketAsyncEventArgs e) { this.LogVerbose(e.SocketError.ToString()); if (e.SocketError != SocketError.Success) { Disconnect(); OnSendError((int)NetErrorCode.UnkownError, e.SocketError.ToString()); return; } var packed = m_currSendingPacket; packed.SentSize += e.BytesTransferred; //将PackedBufferSize的Buffer发送完 if (e.Offset + e.BytesTransferred < e.Count) { var result = true; try { e.SetBuffer(e.Offset + e.BytesTransferred, e.Count - e.BytesTransferred - e.Offset); result = m_socket.SendAsync(e); } catch (Exception ex) { this.LogError("发送数据出错:{0}", ex.Message); } if (!result) { ThreadPool.QueueUserWorkItem(_ => OnSendCompleted(this, e)); } } else { if (!packed.IsSent) { //继续发当前Packet的下一个分组 SendInternal(e); } else { //一个Packet发送完成 m_currSendingPacket = null; m_sending = 0; OnSendSuccess(); //继续发下一个Packet TrySendNext(); } } } protected virtual void OnSendError(int errcode, string info) { this.LogError("{0}:{1}",errcode, info); } protected virtual void OnSendSuccess() { } //====================================================================== //接收数据 //====================================================================== protected void BeginReceive() { ReceiveInternal(); } private void ReceiveInternal() { this.LogVerbose(); bool result = false; try{result = m_socket.ReceiveAsync(m_saeReceive);} catch (Exception ex){this.LogError("接收数据出错:{0}", ex.Message);} if (!result) { ThreadPool.QueueUserWorkItem(_ => OnReceiveCompleted(this, m_saeReceive)); } } private void OnReceiveCompleted(object sender, SocketAsyncEventArgs e) { this.LogVerbose(e.SocketError.ToString()); if (e.SocketError != SocketError.Success) { Disconnect(); OnReceiveError((int)NetErrorCode.UnkownError, e.SocketError.ToString()); return; } if (e.BytesTransferred < 1) { Disconnect(); OnReceiveError((int)NetErrorCode.UnkownError, "收到的字节为0"); return; } if (m_bufferReceive.Capacity < m_bufferReceive.Length + e.BytesTransferred) { //扩容 m_bufferReceive.AdjustCapacity((m_bufferReceive.Length + e.BytesTransferred) * 2); } m_bufferReceive.SetPositionToLength(); m_bufferReceive.WriteBytes(e.Buffer, 0, e.BytesTransferred); this.LogVerbose("Received Length:{0}", m_bufferReceive.Length); while (m_bufferReceive.Length > 0) { m_bufferReceive.Position = 0; NetMessage msg = new NetMessage(); if (msg.Deserialize(m_bufferReceive)) { m_bufferReceive.Arrangement(); lock (m_queueReceive) { m_queueReceive.Enqueue(msg); } } else { this.LogVerbose("Cannot Deserialize One Message!"); break; } } ReceiveInternal(); } protected virtual void OnReceiveError(int errcode, string info) { this.LogError("{0}:{1}", errcode, info); } /// /// 主线程读取数据 /// /// public NetMessage Receive() { NetMessage msg = null; lock (m_queueReceive) { if(m_queueReceive.Count >0) { msg = m_queueReceive.Dequeue(); return msg; } } return null; } } } ================================================ FILE: SGFCore/Network/Utils/DnsUtils.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * DnsUtils * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Net; using SGF.Utils; namespace SGF.Network { public class DnsUtils { public const string TAG = "DnsUtils"; public static string[] GetHostByName(string hostNameOrAddress) { IPAddress ipaddr = null; if (IPAddress.TryParse(hostNameOrAddress, out ipaddr)) { return new string[1] {ipaddr.ToString()}; } IPAddress[] ipAddresses = null; try { ipAddresses = Dns.GetHostAddresses(hostNameOrAddress); } catch (Exception) { } if (ipAddresses != null && ipAddresses.Length > 0) { string[] ipstrs = new string[ipAddresses.Length]; for (int i = 0; i < ipAddresses.Length; i++) { ipstrs[i] = ipAddresses[i].ToString(); } return ipstrs; } return new string[0]; } public static IPAddress[] GetHostAddresses(string hostNameOrAddress) { string[] ipstrs = GetHostByName(hostNameOrAddress); if (ipstrs == null || ipstrs.Length == 0) { return new IPAddress[0]; } List listIPAddrs = new List(); for (int i = 0; i < ipstrs.Length; i++) { IPAddress ipAddress = null; if (IPAddress.TryParse(ipstrs[i], out ipAddress)) { listIPAddrs.Add(ipAddress); } } return listIPAddrs.ToArray(); } public static string[] GetUrlWithIP(string url) { Debuger.Log(TAG, "GetUrlWithIP() old url=" + url); string head, hostname, port, path; UrlUtils.SplitUrl(url, out head, out hostname, out port, out path); string[] ipstrs = GetHostByName(hostname); if (ipstrs == null || ipstrs.Length == 0) { Debuger.Log(TAG, "GetUrlWithIP() domain cannot be parse! new url=" + url); return new string[1] {url}; } Debuger.Log(TAG, "GetUrlWithIP() Can Parse Total " + ipstrs.Length + " url!"); string[] urls = new string[ipstrs.Length]; for (int i = 0; i < ipstrs.Length; i++) { if (string.IsNullOrEmpty(port)) { urls[i] = head + ipstrs[i] + path; } else { urls[i] = head + ipstrs[i] + ":" + port + path; } Debuger.Log(TAG, "GetUrlWithIP() new url[" + (i + 1) + "]=" + urls[i]); } return urls; } } } ================================================ FILE: SGFCore/Network/Utils/IPUtils.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * IPUtils * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; namespace SGF.Network { public class IPUtils { public static bool IOS_IPv6_First = true; //=========================================================== public static readonly IPAddress IP_Broadcast = new IPAddress(0xffffffffL); public static IPEndPoint IPEP_Any = new IPEndPoint(IPAddress.Any, 0); public static IPEndPoint IPEP_IPv6Any = new IPEndPoint(IPAddress.IPv6Any, 0); #region 工具函数:IsBroadcast,IsFatalException,GetIPEndPointAny public static bool IsBroadcast(IPAddress ip) { if (ip.AddressFamily == AddressFamily.InterNetworkV6) { return false; } return ip.Equals(IP_Broadcast); } public static bool IsFatalException(Exception exception) { if (exception == null) { return false; } return (((exception is OutOfMemoryException) || (exception is StackOverflowException)) || (exception is ThreadAbortException)); } public static IPEndPoint GetIPEndPointAny(AddressFamily family, int port) { if (family == AddressFamily.InterNetwork) { if (port == 0) { return IPEP_Any; } return new IPEndPoint(IPAddress.Any, port); } else if (family == AddressFamily.InterNetworkV6) { if (port == 0) { return IPEP_IPv6Any; } return new IPEndPoint(IPAddress.IPv6Any, port); } return null; } #endregion #region 工具函数:获取远程主机的地址 public static IPEndPoint GetHostEndPoint(string host, int port) { IPAddress address = null; if (IPAddress.TryParse(host, out address)) { #if TestIPv6 Debuger.Log("UdpSocket.GetHostEndPoint() TestIPv6: 如果已经是IP了,则封装成IPv6格式"); //已经是一个IP了。在外网下不应该出现IP的情况 if (!address.IsIPv6LinkLocal && !address.IsIPv6SiteLocal) { string tmp = "64:ff9b::" + address.ToString(); IPAddress addr_v6 = null; if (IPAddress.TryParse(tmp, out addr_v6)) { return new IPEndPoint(addr_v6, port); } else { Debuger.LogError("UdpSocket.GetHostEndPoint() TestIPv6,封装IPv6失败:" + tmp); } } #endif return new IPEndPoint(address, port); } else { //如果不是IP,就当作域名来处理 IPAddress[] ips = Dns.GetHostAddresses(host); //如果是IPv6环境,则会返回IPv6的地址,否则会返回IPv4的地址。 if (Debuger.EnableLog) { Debuger.Log("UdpSocket.GetHostEndPoint() Dns GetHostAddresses:"); for (int i = 0; i < ips.Length; i++) { Debuger.Log("[" + i + "] " + ips[i] + ", " + ips[i].AddressFamily); } } List listIPv4 = new List(); List listIPv6 = new List(); for (int i = 0; i < ips.Length; i++) { if (ips[i].AddressFamily == AddressFamily.InterNetwork) { listIPv4.Add(ips[i]); } else { listIPv6.Add(ips[i]); } } #if UNITY_ANDROID if (listIPv4.Count > 0) { return new IPEndPoint(listIPv4[0], port); } if (listIPv6.Count > 0) { return new IPEndPoint(listIPv6[0], port); } #else //加一个静态变量开关,方便以后用Lua设置 if (IOS_IPv6_First) { //IPv6优先 if (listIPv6.Count > 0) { return new IPEndPoint(listIPv6[0], port); } if (listIPv4.Count > 0) { return new IPEndPoint(listIPv4[0], port); } } else { //IPv4优先 if (listIPv4.Count > 0) { return new IPEndPoint(listIPv4[0], port); } if (listIPv6.Count > 0) { return new IPEndPoint(listIPv6[0], port); } } #endif } return null; } #endregion public static string SelfIP { get { string hostName = Dns.GetHostName();//本机名 //System.Net.IPAddress[] addressList = Dns.GetHostByName(hostName).AddressList;//会警告GetHostByName()已过期,我运行时且只返回了一个IPv4的地址 IPAddress[] addressList = Dns.GetHostAddresses("127.0.0.1");//会返回所有地址,包括IPv4和IPv6 return addressList[0].ToString(); } } public static string SelfIP2 { get { string hostname = Dns.GetHostName();//得到本机名 IPHostEntry localhost = Dns.GetHostEntry(hostname); IPAddress localaddr = localhost.AddressList[0]; return localaddr.ToString(); } } public static Int64 IPStr2Int(string ip) { char[] separator = new char[] { '.' }; string[] items = ip.Split(separator); return Int64.Parse(items[0]) << 24 | Int64.Parse(items[1]) << 16 | Int64.Parse(items[2]) << 8 | Int64.Parse(items[3]); } public static string IPInt2Str(Int64 ipInt) { StringBuilder sb = new StringBuilder(); sb.Append((ipInt >> 24) & 0xFF).Append("."); sb.Append((ipInt >> 16) & 0xFF).Append("."); sb.Append((ipInt >> 8) & 0xFF).Append("."); sb.Append(ipInt & 0xFF); return sb.ToString(); } } } ================================================ FILE: SGFCore/Network/Utils/NetUtils.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * NetUtils * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; namespace SGF.Network { public class NetUtils { public static bool GetIsNetworkAvailable() { return NetworkInterface.GetIsNetworkAvailable(); } public static int GetAvaliablePort() { int port = 0; try { var s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); s.Bind(new IPEndPoint(IPAddress.Any, 0)); port = (s.LocalEndPoint as IPEndPoint).Port; s.Close(); } catch (Exception e) { } return port; } } } ================================================ FILE: SGFCore/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // 有关程序集的一般信息由以下 // 控制。更改这些特性值可修改 // 与程序集关联的信息。 [assembly: AssemblyTitle("SGFCore")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("HP Inc.")] [assembly: AssemblyProduct("SGFCore")] [assembly: AssemblyCopyright("Copyright © HP Inc. 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // 将 ComVisible 设置为 false 会使此程序集中的类型 //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 //请将此类型的 ComVisible 特性设置为 true。 [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID [assembly: Guid("eeb72dfc-0fa5-44de-b75a-586f69377aa6")] // 程序集的版本信息由下列四个值组成: // // 主版本 // 次版本 // 生成号 // 修订号 // // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 // 方法是按如下所示使用“*”: : // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: SGFCore/SGFCore.csproj ================================================  Debug AnyCPU {EEB72DFC-0FA5-44DE-B75A-586F69377AA6} Library SGF SGFCore v3.5 512 true AnyCPU true full false ..\Libs\ TRACE;DEBUG;ENABLE_LOG prompt 0 false true AnyCPU pdbonly true ..\Libs\ TRACE prompt 0 false true False ..\Libs\Common\protobuf-net.dll False ..\Libs\SGFDebuger.dll $(ProjectDir)..\Libs\PublishLibrary.bat $(TargetName) ================================================ FILE: SGFCore/SGFCore.csproj.user ================================================  ProjectFiles ================================================ FILE: SGFCore/Server/MainLoop.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 服务器(模块)管理器 * Server (module) manager * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using SGF.Utils; using System.Threading; namespace SGF.Server { public class MainLoop { public static void Run() { Debuger.Log(); while (true) { ServerManager.Instance.Tick(); ConsoleInput.Tick(); Thread.Sleep(1); } } } } ================================================ FILE: SGFCore/Server/ServerConfig.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 服务器(模块)管理器 * Server (module) manager * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using MiniJSON.Safe; using SGF.Utils; namespace SGF.Server { public class ServerModuleInfo { public int id; public string name; public string assembly; public string ip; public int port; public bool auto; } public class ServerConfig { public static string Namespace = "SGF.Server"; internal readonly static string DefaultPath = "./ServerConfig.json"; private readonly static MapList MapServerModuleInfo = new MapList(); public static void Load(string path = null) { MapServerModuleInfo.Clear(); if (string.IsNullOrEmpty(path)) { path = DefaultPath; } ReadConfig(path); } public static ServerModuleInfo GetServerModuleInfo(int id) { if (MapServerModuleInfo.Count == 0) { ReadConfig(DefaultPath); } return MapServerModuleInfo[id]; } public static void SetServerModuleInfo(ServerModuleInfo info) { MapServerModuleInfo[info.id] = info; } public static ServerModuleInfo[] GetServerModuleInfoList() { return MapServerModuleInfo.ToArray(); } private static void ReadConfig(string path) { Debuger.Log(); string jsonStr = FileUtils.ReadString(path); List obj = null; try { obj = Json.Deserialize(jsonStr) as List; } catch (Exception e) { Debuger.LogError("文件加载失败:{0}", path); return; } for (int i = 0; i < obj.Count; i++) { var infoJson = obj[i] as Dictionary; ServerModuleInfo info = new ServerModuleInfo(); info.id = (int)infoJson["id"]; info.name = (string)infoJson["name"]; info.assembly = (string)infoJson["assembly"]; info.ip = (string)infoJson["ip"]; info.port = (int)infoJson["port"]; info.auto = (bool)infoJson["auto"]; MapServerModuleInfo.Add(info.id, info); } } } } ================================================ FILE: SGFCore/Server/ServerManager.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 服务器(模块)管理器 * Server (module) manager * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using SGF.Utils; namespace SGF.Server { public class ModuleMessageHandlerAttribute : Attribute { } public class ServerManager:Singleton { class MessageObject { public int target; public string msg; public object[] args; } private MapList m_mapModule = new MapList(); private Dictionary> m_mapCacheMessage = new Dictionary>(); private Queue m_queueMessage = new Queue(); public void Init(string _namespace) { ServerConfig.Namespace = _namespace; } public void StartAutoServer() { ServerConfig.Load(); var list = ServerConfig.GetServerModuleInfoList(); for (int i = 0; i < list.Length; i++) { if (list[i].auto) { StartServer(list[i]); } } } public void StartServer(int id) { Debuger.Log(id); ServerModuleInfo info = ServerConfig.GetServerModuleInfo(id); StartServer(info); } public bool StartServer(ServerModuleInfo info) { string fullName = ServerConfig.Namespace + "." + info.name + "." + info.name; Debuger.Log(fullName); try { Type type = Type.GetType(fullName + "," + info.assembly); var module = Activator.CreateInstance(type) as ServerModule; if (module != null) { module.Create(info); m_mapModule.Add(info.id, module); module.Start(); ServerConfig.SetServerModuleInfo(info); //处理缓存的消息 if (m_mapCacheMessage.ContainsKey(info.id)) { List list = m_mapCacheMessage[info.id]; for (int i = 0; i < list.Count; i++) { MessageObject msgobj = list[i]; module.HandleMessage(msgobj.msg, msgobj.args); } m_mapCacheMessage.Remove(info.id); } return true; } } catch (Exception e) { m_mapModule.Remove(info.id); Debuger.LogError("ServerModule[{0}] Create Or Start Error:{1}", info.name, e.Message + "\n" + e.StackTrace); } return false; } public void StopServer(int id) { Debuger.Log(id); var moudule = m_mapModule[id]; if (moudule != null) { moudule.Stop(); moudule.Release(); m_mapModule.Remove(id); } } public void StopAllServer() { Debuger.Log(); var list = m_mapModule.AsList(); int cnt = list.Count; for (int i = 0; i < cnt; i++) { list[i].Stop(); list[i].Release(); } m_mapModule.Clear(); } public void Tick() { //Post 消息 //不管消息 来自哪个线程,都应该由主线程处理@Slicol lock (m_queueMessage) { while (m_queueMessage.Count > 0) { var obj = m_queueMessage.Dequeue(); var m = GetModule(obj.target); if (m != null) { m.HandleMessage(obj.msg, obj.args); } else { Debuger.LogWarning("消息被丢弃! target:{0}, msg:{1}", obj.target, obj.msg); } } } var list = m_mapModule.AsList(); int cnt = list.Count; for (int i = 0; i < cnt; i++) { list[i].Tick(); } } public bool HasModule(int id) { return m_mapModule.ContainsKey(id); } public ServerModule GetModule(int id) { ServerModule module = m_mapModule[id]; return module; } //============================================================================ //消息机制 //============================================================================ public void SendMessage(int target, string msg, params object[] args) { ServerModule module = GetModule(target); if (module != null) { module.HandleMessage(msg, args); } else { var list = GetCacheMessageList(target); MessageObject obj = new MessageObject(); obj.msg = msg; obj.args = args; obj.target = target; list.Add(obj); } } public void PostMessage(int target, string msg, params object[] args) { System.Threading.ThreadPool.QueueUserWorkItem(_ => PostMessageInternal(target, msg, args)); } private void PostMessageInternal(int target, string msg, object[] args) { MessageObject obj = new MessageObject(); obj.msg = msg; obj.args = args; obj.target = target; lock (m_queueMessage) { m_queueMessage.Enqueue(obj); } } private List GetCacheMessageList(int target) { List list = null; if (!m_mapCacheMessage.TryGetValue(target, out list)) { list = new List(); m_mapCacheMessage.Add(target, list); } return list; } } } ================================================ FILE: SGFCore/Server/ServerModule.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 服务器(模块)管理器 * Server (module) manager * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System.Reflection; namespace SGF.Server { public class ServerModule:ILogTag { private ServerModuleInfo m_info; private object m_msgHandler; public int id { get { return m_info.id; } } public int port { get { return m_info.port; } } internal void Create(ServerModuleInfo info) { m_info = info; m_msgHandler = this; LOG_TAG = this.GetType().Name + "[" + info.id + "," + info.port + "]"; this.Log(); } internal void Release() { this.Log(); } public virtual void Start() { this.Log(); } public virtual void Stop() { this.Log(); } public virtual void Tick() { } public void BindModuleMessageHandler(object handler) { m_msgHandler = handler == null ? this : handler; } /// /// 当模块收到消息后,对消息进行一些处理 /// /// /// internal void HandleMessage(string msg, object[] args) { this.Log("msg:{0}, args:{1}", msg, args); var mi = m_msgHandler.GetType().GetMethod(msg, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); if (mi != null) { mi.Invoke(m_msgHandler, BindingFlags.NonPublic, null, args, null); } else { OnModuleMessage(msg, args); } } /// /// 由派生类去实现,用于处理消息 /// /// /// protected virtual void OnModuleMessage(string msg, object[] args) { this.Log("msg:{0}, args{1}", msg, args); } public string LOG_TAG { get; private set; } } } ================================================ FILE: SGFCore/Threading/ThreadPool.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Threading; namespace SGF.Threading { public class ThreadPool { class ThreadTaskState { public object[] args; public Delegate func; } public static int maxThreads = 8; private static int numThreads = 0; private static List ms_listFuncOnMainThread = new List(); private static List ms_currentInvokingFuncs = new List(); private static Delegate ms_funcThreadWorker; public static void QueueOnMainThread(Delegate func, params object[] args) { lock (ms_listFuncOnMainThread) { var state = new ThreadTaskState() { args = args, func = func }; ms_listFuncOnMainThread.Add(state); } } public static Thread QueueUserWorkItem(Delegate func, params object[] args) { if (ms_funcThreadWorker == null) { ms_funcThreadWorker = (WaitCallback)ThreadWorker; } while (numThreads >= maxThreads) { Thread.Sleep(1); } Interlocked.Increment(ref numThreads); try { //如果线程不够了,就直接执行 var state = new ThreadTaskState() { args = args, func = func }; System.Threading.ThreadPool.QueueUserWorkItem((WaitCallback)(ms_funcThreadWorker), state); } catch (Exception e) { ((Action)func)(args); Interlocked.Decrement(ref numThreads); } finally { } return null; } private static void ThreadWorker(object obj) { try { ThreadTaskState state = obj as ThreadTaskState; ((Action)state.func)(state.args); } catch { } finally { Interlocked.Decrement(ref numThreads); } } public static void TickOnMainThread() { lock (ms_listFuncOnMainThread) { ms_currentInvokingFuncs.Clear(); ms_currentInvokingFuncs.AddRange(ms_listFuncOnMainThread); ms_listFuncOnMainThread.Clear(); } foreach (var state in ms_currentInvokingFuncs) { try { ((Action)state.func)(state.args); } catch (Exception e) { Debuger.LogWarning(e.Message); } } } } } ================================================ FILE: SGFCore/Timers/Timer.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace SGF.Timers { public delegate void ElapsedEventHandler(object sender, ElapsedEventArgs e); public class ElapsedEventArgs : EventArgs { private DateTime signalTime; public DateTime SignalTime { get { return this.signalTime; } } internal ElapsedEventArgs() { signalTime = DateTime.Now; } } public class Timer:IDisposable { //========================================================================= #region ////Timer Manager//// private static List m_timers = new List(); private static long m_lastTicks = 0; private static void AddTimer(Timer timer) { if(!m_timers.Contains(timer)) { m_timers.Add(timer); } } private static void RemoveTimer(Timer timer) { try { m_timers.Remove(timer); } catch { } } public static void Tick() { var now = DateTime.Now.Ticks; var dt = now - m_lastTicks; m_lastTicks = now; Tick(GetMillisecondsFromTicks(dt)); } public static void Tick(double dt) { var timers = m_timers.ToArray(); for(int i =0;i < timers.Length; ++i) { timers[i].TickInternal(dt); } } public static double GetMillisecondsFromTicks(long ticks) { return ticks / 10000.0f; } #endregion //========================================================================= private bool m_disposed = false; private double m_elapsed = 0; private double m_interval; private int m_count; private bool m_enabled; private bool m_autoReset = false; public ElapsedEventHandler onIntervalElapsed; public Timer() { m_interval = 100; m_enabled = false; m_autoReset = true; } public Timer(double interval) { if (interval <= 0) interval = 0; double roundedInterval = Math.Ceiling(interval); if (roundedInterval > Int32.MaxValue || roundedInterval <= 0) { roundedInterval = 0; } this.m_interval = (int)roundedInterval; } ~Timer() { Dispose(); } public void Dispose() { if (m_disposed) return; m_disposed = true; Close(); } public void Close() { m_enabled = false; RemoveTimer(this); } public bool AutoReset { get { return this.m_autoReset; } set { if (this.m_autoReset != value) { this.m_autoReset = value; if(value) { Enabled = true; } } } } public bool Enabled { get { return m_enabled; } set { if (m_enabled != value) { m_enabled = value; if (!value) { RemoveTimer(this); } else { AddTimer(this); } } } } public double Interval { get { return this.m_interval; } set { m_interval = value; } } public event ElapsedEventHandler Elapsed { add { onIntervalElapsed += value; } remove { onIntervalElapsed -= value; } } public void Start() { Enabled = true; } public void Stop() { Enabled = false; } internal void TickInternal(double dt) { m_elapsed += dt; if(m_elapsed >= m_interval) { m_elapsed -= m_interval; if (!this.m_autoReset) { Enabled = false; } try { ElapsedEventHandler intervalElapsed = this.onIntervalElapsed; if (intervalElapsed != null) { ElapsedEventArgs elapsedEventArgs = new ElapsedEventArgs(); intervalElapsed(this, elapsedEventArgs); } } catch { } } } } } ================================================ FILE: SGFCore/Utils/AppPrefs.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using MiniJSON.Safe; namespace SGF.Utils { public static class AppPrefs { private static string m_path; private static JsonObject m_jobj = new JsonObject(); public static void Init(string path) { m_path = path; var str = FileUtils.ReadString(m_path); if (!string.IsNullOrEmpty(str)) { try { m_jobj = Json.Deserialize(str) as JsonObject; } catch (Exception e) { } } if(m_jobj == null) m_jobj = new JsonObject(); } // public static float GetFloat(string key, float defaultValue = 0) { var obj = m_jobj[GetKey(key)]; if (obj == null) return defaultValue; return (float)Convert.ToDouble(obj); } public static int GetInt(string key, int defaultValue = 0) { var obj = m_jobj[GetKey(key)]; if (obj == null) return defaultValue; return (int)Convert.ToInt32(obj); } public static string GetString(string key, string defaultValue = "") { var obj = m_jobj[GetKey(key)]; if (obj == null) return defaultValue; return (string)obj; } // public static bool HasKey(string key) { return m_jobj.ContainsKey(GetKey(key)); } // public static void SetFloat(string key, float value) { m_jobj[GetKey(key)] = value; } // public static void SetInt(string key, int value) { m_jobj[GetKey(key)] = value; } // public static void SetString(string key, string value) { m_jobj[GetKey(key)] = value; } public static void DeleteAll() { m_jobj.Clear(); } // public static void DeleteKey(string key) { if (m_jobj.ContainsKey(GetKey(key))) { m_jobj.Remove(GetKey(key)); } } public static void Save() { var str = Json.Serialize(m_jobj); FileUtils.SaveFile(m_path, str); } private static string GetKey(string key) { return key; } } } ================================================ FILE: SGFCore/Utils/CmdlineUtils.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using SGF.Extension; namespace SGF.Utils { public class CmdlineUtils { public static string GetArgValue(string[] args, string name) { for (int i = 0; i < args.Length; i++) { var token = args[i]; if (token.ToLower() == name) { if (i < args.Length - 1) { return args[i + 1]; } } } return ""; } public static bool HasArg(string[] args, string name) { for (int i = 0; i < args.Length; i++) { var token = args[i]; if (token.ToLower() == name) { return true; } } return false; } public static int GetArgInt(string[] args, string name) { return GetArgValue(args, name).ToInt(); } public static float GetArgFloat(string[] args, string name) { return GetArgValue(args, name).ToFloat(); } public static bool GetArgBool(string[] args, string name) { return GetArgValue(args, name) == "true"; } } } ================================================ FILE: SGFCore/Utils/ConsoleInput.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 通过事件的方式监听来自控制台的输入 * Monitor input from the console by way of events * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using SGF.SEvent; namespace SGF.Utils { public class ConsoleInput { enum InputState { Idle = 0, Inputing = 1 } public readonly static Signal onInputLine = new Signal(); public readonly static Signal onInputKey = new Signal(); private static InputState ms_InputState = InputState.Idle; private static string ms_InputBuffer = ""; public static void Tick() { if (Console.KeyAvailable) { ConsoleKeyInfo info = Console.ReadKey(); if (ms_InputState == InputState.Inputing) { if (info.Key == ConsoleKey.Enter) { ms_InputState = InputState.Idle; Console.WriteLine();//输入框消失 onInputLine.Invoke(ms_InputBuffer); } else if (info.Key == ConsoleKey.Escape) { ms_InputState = InputState.Idle; Console.WriteLine();//输入框消失 } else if (info.Key >= ConsoleKey.A && info.Key <= ConsoleKey.Z) { ms_InputBuffer += info.KeyChar; } else if (info.Key >= ConsoleKey.D0 && info.Key <= ConsoleKey.D9) { ms_InputBuffer += info.KeyChar; } else { ms_InputBuffer += info.KeyChar; } } else if(ms_InputState == InputState.Idle) { onInputKey.Invoke(info.Key); if (info.Key == ConsoleKey.Enter) { ms_InputState = InputState.Inputing; ms_InputBuffer = ""; //显示一个输入框 Console.Write("Input:"); } } } } } } ================================================ FILE: SGFCore/Utils/DictionarySafe.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 封装Dictionary以提供简捷而安全的使用方式 * Encapsulate Dictionary to provide simple and safe use * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; namespace SGF.Utils { public class DictionarySafe : Dictionary { public new TValue this[TKey key] { set { base[key] = value; } get { TValue value = default(TValue); TryGetValue(key, out value); return value; } } } } ================================================ FILE: SGFCore/Utils/FPSUtils.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Text; namespace SGF.Utils { public static class FPSUtils { public class FPSStatInfo { public string tag; public long beginTime; internal uint beginFrame; public long timeLength; public uint frameCount; } private static uint m_frameIndex = 0; private static Stack m_stack = new Stack(); private static List m_listResult = new List(); /// /// 不支持嵌套 /// /// public static void Begin(string tag) { FPSStatInfo info = new FPSStatInfo(); info.tag = tag; info.beginFrame = m_frameIndex; info.beginTime = DateTime.Now.Ticks; m_stack.Push(info); } public static void End() { if (m_stack.Count > 0) { var info = m_stack.Pop(); info.timeLength = DateTime.Now.Ticks - info.beginTime; info.frameCount = m_frameIndex - info.beginFrame; m_listResult.Add(info); } else { Debuger.LogError("Begin与End没有成对调用!"); } } public static void Update() { ++m_frameIndex; } public static float GetAverageFPS(string tag) { long totalTime = 0; uint totalFrame = 0; for (int i = 0; i < m_listResult.Count; i++) { var info = m_listResult[i]; if (info.tag == tag) { totalTime += info.timeLength; totalTime += info.frameCount; } } return (float)(totalFrame / TimeUtils.GetSecondsFromTicks(totalTime)); } public static FPSStatInfo[] GetFPSStatInfos() { return m_listResult.ToArray(); } public static string GetDumpString(bool cluster = false) { StringBuilder sb = new StringBuilder(); if (cluster) { Dictionary mapFPS = new Dictionary(); for (int i = 0; i < m_listResult.Count; i++) { var info = m_listResult[i]; long[] tmp = null; if (!mapFPS.TryGetValue(info.tag, out tmp)) { tmp = new long[2]; mapFPS.Add(info.tag, tmp); } tmp[0] += info.timeLength; tmp[1] += info.frameCount; } sb.AppendFormat("{0,2}. {1,5} {2}\n", "#", "FPS", "Tag"); int j = 0; foreach (var pair in mapFPS) { var tag = pair.Key; float fps = (float)(pair.Value[1] / TimeUtils.GetSecondsFromTicks(pair.Value[0])); sb.AppendFormat("{0,2}. {1,5} {2}\n", j, fps, tag); j++; } sb.AppendFormat("-----------------------------\n"); } else { sb.AppendFormat("{0,2}. {1,5} {2}\n", "#", "FPS", "Tag"); for (int i = 0; i < m_listResult.Count; i++) { var info = m_listResult[i]; float fps = (float)(info.frameCount / TimeUtils.GetSecondsFromTicks(info.timeLength)); sb.AppendFormat("{0,2}. {1,5} {2}\n", i, fps, info.tag); } sb.AppendFormat("-----------------------------\n"); } return sb.ToString(); } } } ================================================ FILE: SGFCore/Utils/FileUtils.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * FileUtils * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Runtime.InteropServices; using System.Text; using SGF.Marshals; namespace SGF.Utils { public class FileUtils { public static byte[] ReadFile(string fullpath, int readsize = 0) { byte[] buffer = null; if (File.Exists(fullpath)) { FileStream fs = null; try { fs = new FileStream(fullpath, FileMode.Open, FileAccess.Read); if (readsize == 0 || readsize >= fs.Length) { buffer = new byte[fs.Length]; } else { buffer = new byte[readsize]; } fs.Read(buffer, 0, buffer.Length); } catch (Exception e) { Debuger.LogError("ReadFile() Path:{0}, Error:{1}", fullpath, e.Message); } finally { if (fs != null) { fs.Close(); } } } else { Debuger.LogError("ReadFile() File is Not Exist: {0}", fullpath); } return buffer; } public static string[] ReadFileLines(string fullpath) { List listLines = new List(); if (File.Exists(fullpath)) { StreamReader fs = null; try { fs = new StreamReader(fullpath); while (fs.Peek() > 0) { listLines.Add(fs.ReadLine()); } } catch (Exception e) { Debuger.LogError("ReadFileLines() Path:{0}, Error:{1}", fullpath, e.Message); } finally { if (fs != null) { fs.Close(); } } } else { Debuger.LogError("ReadFileLines() File is Not Exist: {0}", fullpath); } return listLines.ToArray(); } public static string ReadString(string fullpath) { byte[] buffer = ReadFile(fullpath); if (buffer != null) { return Encoding.UTF8.GetString(buffer); } return ""; } public static string ReadStringASCII(string fullpath) { byte[] buffer = ReadFile(fullpath); if (buffer != null) { return Encoding.ASCII.GetString(buffer); } return ""; } public static int SaveFile(string fullpath, byte[] content) { if (content == null) { content = new byte[0]; } string dir = PathUtils.GetParentDir(fullpath); if (!Directory.Exists(dir)) { try { Directory.CreateDirectory(dir); } catch (Exception e) { Debuger.LogError("SaveFile() CreateDirectory Error! Dir:{0}, Error:{1}", dir, e.Message); return -1; } } FileStream fs = null; try { fs = new FileStream(fullpath, FileMode.Create, FileAccess.Write); fs.Write(content, 0, content.Length); } catch (Exception e) { Debuger.LogError("SaveFile() Path:{0}, Error:{1}", fullpath, e.Message); fs.Close(); return -1; } fs.Close(); return content.Length; } public static int SaveFile(string fullpath, string content) { byte[] buffer = Encoding.UTF8.GetBytes(content); return SaveFile(fullpath, buffer); } public static List GetFileFullNames(string dir, SearchOption option, string searchPattern, string[] listIgnoredSuffix = null) { List result = new List(); var list = GetFiles(dir, option, searchPattern, listIgnoredSuffix); for (int i = 0; i < list.Count; i++) { result.Add(list[i].FullName); } return result; } public static List GetFileNames(string dir, SearchOption option, string searchPattern, string[] listIgnoredSuffix = null) { List result = new List(); var list = GetFiles(dir, option, searchPattern, listIgnoredSuffix); for (int i = 0; i < list.Count; i++) { result.Add(list[i].Name); } return result; } public static List GetFiles(string dir, SearchOption option, string searchPattern, string[] listIgnoredSuffix = null) { List result = new List(); if (Directory.Exists(dir)) { DirectoryInfo directory = new DirectoryInfo(dir); FileInfo[] files = directory.GetFiles(searchPattern, option); int len = files.Length; for (int i = 0; i < len; i++) { FileInfo f = files[i]; bool ignored = false; if (listIgnoredSuffix != null) { int lenIgnored = listIgnoredSuffix.Length; for (int j = 0; j < lenIgnored; j++) { if (f.FullName.EndsWith(listIgnoredSuffix[j])) { ignored = true; break; } } } if (!ignored) { result.Add(f); } } } return result; } public static void EnsureDirectory(string dirPath) { dirPath = dirPath.Replace('\\', '/'); var tokens = dirPath.Split('/'); string dstTempPath = ""; for (int i = 0; i < tokens.Length; i++) { dstTempPath += tokens[i] + "/"; if (!Directory.Exists(dstTempPath)) { Directory.CreateDirectory(dstTempPath); } } } public static void EnsureFileDirectory(string filePath) { filePath = filePath.Replace('\\', '/'); var tokens = filePath.Split('/'); string dstTempPath = ""; for (int i = 0; i < tokens.Length - 1; i++) { dstTempPath += tokens[i] + "/"; if (!Directory.Exists(dstTempPath)) { Directory.CreateDirectory(dstTempPath); } } } public static bool Copy(string srcPath, string dstPath) { if (!File.Exists(srcPath)) { return false; } EnsureFileDirectory(dstPath); try { File.Copy(srcPath, dstPath); return true; } catch (Exception e) { Debuger.LogError(e.Message); } return false; } } } ================================================ FILE: SGFCore/Utils/MapList.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 将Dictionary与List封装在一起,以满足既需要快速遍历,又需要快速按Key存取的需求 * Wrap the Dictionary and List together to meet the need for fast traversal and fast key access * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Linq; namespace SGF.Utils { public class MapList { private Dictionary m_map; private List m_list; public MapList(int capacity) { m_map = new Dictionary(capacity); m_list = new List(capacity); } public MapList() { m_map = new Dictionary(); m_list = new List(); } public List AsList() { return m_list; } public Dictionary AsDictionary() { return m_map; } public List ToList() { return m_list.ToList(); } public TValue[] ToArray() { return m_list.ToArray(); } public new TValue this[TKey indexKey] { set { if (m_map.ContainsKey(indexKey)) { TValue v = m_map[indexKey]; m_map[indexKey] = value; m_list.Remove(v); m_list.Add(value); } else { m_map.Add(indexKey, value); m_list.Add(value); } } get { TValue value = default(TValue); m_map.TryGetValue(indexKey, out value); return value; } } public bool Add(TKey key, TValue value) { if (m_map.ContainsKey(key)) { return false; } m_map.Add(key, value); m_list.Add(value); return true; } public bool Remove(TKey key) { if (m_map.ContainsKey(key)) { TValue v = m_map[key]; m_list.Remove(v); return m_map.Remove(key); } return false; } public bool RemoveAt(int index, TKey key) { m_list.RemoveAt(index); return m_map.Remove(key); } public void Clear() { m_map.Clear(); m_list.Clear(); } public int Count { get { return m_list.Count; } } public bool ContainsKey(TKey key) { return m_map.ContainsKey(key); } } } ================================================ FILE: SGFCore/Utils/ObjectDumpUtils.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System.Collections; using System.Text; namespace SGF.Utils { public class ObjectDumpUtils { public static void Dump(string name, object obj, StringBuilder result, string prefix = "") { if (obj == null) { return; } var type = obj.GetType(); if (type == typeof(int) || type == typeof(uint) || type == typeof(short) || type == typeof(ushort) || type == typeof(long) || type == typeof(ulong) || type == typeof(byte) || type == typeof(float) || type == typeof(double) || type == typeof(string) || type == typeof(bool) ) { result.AppendFormat("{0}{1}:{2}\n", prefix, name, obj); return; } result.AppendFormat("{0}{1}:\n", prefix, name); if (obj is IList) { var list = obj as IList; for (int i = 0; i < list.Count; i++) { var tmp = list[i]; Dump("[" + i + "]", tmp, result, prefix + " "); } return; } var fields = type.GetFields(); for (int i = 0; i < fields.Length; i++) { var fi = fields[i]; var f = fi.GetValue(obj); if (fi.Name == "MaxValue" || fi.Name == "MinValue") { continue; } Dump(fi.Name, f, result, prefix + " "); } } } } ================================================ FILE: SGFCore/Utils/PathUtils.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * PathUtils * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ namespace SGF.Utils { public class PathUtils { public static readonly string[] PathHeadDefine = { "jar://", "jar:file:///", "file:///", "http://", "https://" }; public static bool IsSureDir(string path) { int i = path.LastIndexOf("/"); if (i >= 0) { return true; } i = path.LastIndexOf("\\"); if (i >= 0) { return true; } return false; } public static bool IsFullPath(string path) { int i = path.IndexOf(":/"); if (i >= 0) { return true; } i = path.IndexOf(":\\"); if (i >= 0) { return true; } return false; } public static string GetFileName(string path) { string parent = "", child = ""; SplitPath(path, ref parent, ref child, true); return child; } public static string GetParentDir(string path) { string parent = "", child = ""; SplitPath(path, ref parent, ref child, true); return parent; } public static string SplitPath(string path, ref string parent, ref string child, bool bSplitExt = false) { string ext = ""; string head = SplitPath(path, ref parent, ref child, ref ext); if (bSplitExt) { return head; } if (!string.IsNullOrEmpty(ext)) { child = child + "." + ext; } return head; } public static string SplitPath(string path, ref string parent, ref string child, ref string ext) { string head = GetPathHead(path); int index = path.LastIndexOf("/"); int index2 = path.LastIndexOf("\\"); index = System.Math.Max(index, index2); if (index == head.Length - 1) { parent = ""; child = path; } else { parent = path.Substring(0, index); child = path.Substring(index + 1); } index = child.LastIndexOf("."); if (index >= 0) { ext = child.Substring(index + 1); child = child.Substring(0, index); } return head; } public static string GetPathHead(string path) { for (int i = 0; i < PathHeadDefine.Length; i++) { if (path.StartsWith(PathHeadDefine[i])) { return PathHeadDefine[i]; } } return ""; } } } ================================================ FILE: SGFCore/Utils/SGFTime.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * 类似Unity里的Time类。 * 需要在App启动时,进行初始化。 * Similar to the Time class in Unity. * It needs to be initialized when the app starts. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; namespace SGF.Time { public class SGFTime { public static DateTime DateTimeAppStart = new DateTime(1970, 1, 1, 8, 0, 0); public static float GetTimeSinceStartup() { DateTime nowtime = DateTime.Now.ToLocalTime(); return (float)(nowtime.Subtract(DateTimeAppStart).TotalSeconds); } } } ================================================ FILE: SGFCore/Utils/Singleton.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Singleton * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ namespace SGF.Utils { public abstract class Singleton where T : Singleton, new() { private static T ms_instance = default(T); public static T Instance { get { if (ms_instance == null) { ms_instance = new T(); ms_instance.InitSingleton(); } return ms_instance; } } protected virtual void InitSingleton() { } } //********************************************************************** } ================================================ FILE: SGFCore/Utils/StringUtils.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections; using System.Text; namespace SGF.Utils { public static class StringUtils { private static StringBuilder ms_temp = new StringBuilder(); public static string ToString(Array target) { ms_temp.Length = 0; ms_temp.Append("["); if (target.Length > 0) { ms_temp.Append(target.GetValue(0)); } for (int i = 1; i < target.Length; i++) { ms_temp.Append(","); ms_temp.Append(target.GetValue(i)); } ms_temp.Append("]"); return ms_temp.ToString(); } public static string ToString(IList target) { ms_temp.Length = 0; ms_temp.Append("["); if (target.Count > 0) { ms_temp.Append(target[0]); } for (int i = 1; i < target.Count; i++) { ms_temp.Append(","); ms_temp.Append(target[i]); } ms_temp.Append("]"); return ms_temp.ToString(); } } } ================================================ FILE: SGFCore/Utils/ThrowHelper.cs ================================================ using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Security; namespace SGF.Utils { internal enum ExceptionArgument { obj, dictionary, dictionaryCreationThreshold, array, info, key, collection, list, match, converter, queue, stack, capacity, index, startIndex, value, count, arrayIndex, name, mode, } internal enum ExceptionResource { Argument_ImplementIComparable, Argument_InvalidType, Argument_InvalidArgumentForComparison, Argument_InvalidRegistryKeyPermissionCheck, ArgumentOutOfRange_NeedNonNegNum, Arg_ArrayPlusOffTooSmall, Arg_NonZeroLowerBound, Arg_RankMultiDimNotSupported, Arg_RegKeyDelHive, Arg_RegKeyStrLenBug, Arg_RegSetStrArrNull, Arg_RegSetMismatchedKind, Arg_RegSubKeyAbsent, Arg_RegSubKeyValueAbsent, Argument_AddingDuplicate, Serialization_InvalidOnDeser, Serialization_MissingKeyValuePairs, Serialization_NullKey, Argument_InvalidArrayType, NotSupported_KeyCollectionSet, NotSupported_ValueCollectionSet, ArgumentOutOfRange_SmallCapacity, ArgumentOutOfRange_Index, Argument_InvalidOffLen, Argument_ItemNotExist, ArgumentOutOfRange_Count, ArgumentOutOfRange_InvalidThreshold, ArgumentOutOfRange_ListInsert, NotSupported_ReadOnlyCollection, InvalidOperation_CannotRemoveFromStackOrQueue, InvalidOperation_EmptyQueue, InvalidOperation_EnumOpCantHappen, InvalidOperation_EnumFailedVersion, InvalidOperation_EmptyStack, ArgumentOutOfRange_BiggerThanCollection, InvalidOperation_EnumNotStarted, InvalidOperation_EnumEnded, NotSupported_SortedListNestedWrite, InvalidOperation_NoValue, InvalidOperation_RegRemoveSubKey, Security_RegistryPermission, UnauthorizedAccess_RegistryNoWrite, ObjectDisposed_RegKeyClosed, NotSupported_InComparableType, } internal static class ThrowHelper { [MethodImpl(MethodImplOptions.NoInlining)] internal static void ThrowArgumentOutOfRangeException() { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index); } internal static void ThrowWrongKeyTypeArgumentException(object key, Type targetType) { throw new ArgumentException("WrongKeyTypeArgumentException"); } internal static void ThrowWrongValueTypeArgumentException(object value, Type targetType) { throw new ArgumentException("WrongValueTypeArgumentException"); } internal static void ThrowKeyNotFoundException() { throw new KeyNotFoundException(); } internal static void ThrowArgumentException(ExceptionResource resource) { throw new ArgumentException("ArgumentException:" + ThrowHelper.GetResourceName(resource)); } internal static void ThrowArgumentException(ExceptionResource resource, ExceptionArgument argument) { throw new ArgumentException("ArgumentException:" + (ThrowHelper.GetResourceName(resource)), ThrowHelper.GetArgumentName(argument)); } internal static void ThrowArgumentNullException(ExceptionArgument argument) { throw new ArgumentNullException(ThrowHelper.GetArgumentName(argument)); } internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument) { throw new ArgumentOutOfRangeException(ThrowHelper.GetArgumentName(argument)); } internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource) { throw new ArgumentOutOfRangeException(ThrowHelper.GetArgumentName(argument), (ThrowHelper.GetResourceName(resource))); } internal static void ThrowInvalidOperationException(ExceptionResource resource) { throw new InvalidOperationException((ThrowHelper.GetResourceName(resource))); } internal static void ThrowSerializationException(ExceptionResource resource) { throw new SerializationException((ThrowHelper.GetResourceName(resource))); } internal static void ThrowSecurityException(ExceptionResource resource) { throw new SecurityException((ThrowHelper.GetResourceName(resource))); } internal static void ThrowNotSupportedException(ExceptionResource resource) { throw new NotSupportedException((ThrowHelper.GetResourceName(resource))); } internal static void ThrowUnauthorizedAccessException(ExceptionResource resource) { throw new UnauthorizedAccessException((ThrowHelper.GetResourceName(resource))); } internal static void ThrowObjectDisposedException(string objectName, ExceptionResource resource) { throw new ObjectDisposedException(objectName, (ThrowHelper.GetResourceName(resource))); } internal static string GetArgumentName(ExceptionArgument argument) { switch (argument) { case ExceptionArgument.obj: return "obj"; case ExceptionArgument.dictionary: return "dictionary"; case ExceptionArgument.dictionaryCreationThreshold: return "dictionaryCreationThreshold"; case ExceptionArgument.array: return "array"; case ExceptionArgument.info: return "info"; case ExceptionArgument.key: return "key"; case ExceptionArgument.collection: return "collection"; case ExceptionArgument.list: return "list"; case ExceptionArgument.match: return "match"; case ExceptionArgument.converter: return "converter"; case ExceptionArgument.queue: return "queue"; case ExceptionArgument.stack: return "stack"; case ExceptionArgument.capacity: return "capacity"; case ExceptionArgument.index: return "index"; case ExceptionArgument.startIndex: return "startIndex"; case ExceptionArgument.value: return "value"; case ExceptionArgument.count: return "count"; case ExceptionArgument.arrayIndex: return "arrayIndex"; case ExceptionArgument.name: return "name"; case ExceptionArgument.mode: return "mode"; default: return string.Empty; } } internal static string GetResourceName(ExceptionResource resource) { switch (resource) { case ExceptionResource.Argument_ImplementIComparable: return "Argument_ImplementIComparable"; case ExceptionResource.Argument_InvalidType: return "Argument_InvalidType"; case ExceptionResource.Argument_InvalidArgumentForComparison: return "Argument_InvalidArgumentForComparison"; case ExceptionResource.Argument_InvalidRegistryKeyPermissionCheck: return "Argument_InvalidRegistryKeyPermissionCheck"; case ExceptionResource.ArgumentOutOfRange_NeedNonNegNum: return "ArgumentOutOfRange_NeedNonNegNum"; case ExceptionResource.Arg_ArrayPlusOffTooSmall: return "Arg_ArrayPlusOffTooSmall"; case ExceptionResource.Arg_NonZeroLowerBound: return "Arg_NonZeroLowerBound"; case ExceptionResource.Arg_RankMultiDimNotSupported: return "Arg_RankMultiDimNotSupported"; case ExceptionResource.Arg_RegKeyDelHive: return "Arg_RegKeyDelHive"; case ExceptionResource.Arg_RegKeyStrLenBug: return "Arg_RegKeyStrLenBug"; case ExceptionResource.Arg_RegSetStrArrNull: return "Arg_RegSetStrArrNull"; case ExceptionResource.Arg_RegSetMismatchedKind: return "Arg_RegSetMismatchedKind"; case ExceptionResource.Arg_RegSubKeyAbsent: return "Arg_RegSubKeyAbsent"; case ExceptionResource.Arg_RegSubKeyValueAbsent: return "Arg_RegSubKeyValueAbsent"; case ExceptionResource.Argument_AddingDuplicate: return "Argument_AddingDuplicate"; case ExceptionResource.Serialization_InvalidOnDeser: return "Serialization_InvalidOnDeser"; case ExceptionResource.Serialization_MissingKeyValuePairs: return "Serialization_MissingKeyValuePairs"; case ExceptionResource.Serialization_NullKey: return "Serialization_NullKey"; case ExceptionResource.Argument_InvalidArrayType: return "Argument_InvalidArrayType"; case ExceptionResource.NotSupported_KeyCollectionSet: return "NotSupported_KeyCollectionSet"; case ExceptionResource.NotSupported_ValueCollectionSet: return "NotSupported_ValueCollectionSet"; case ExceptionResource.ArgumentOutOfRange_SmallCapacity: return "ArgumentOutOfRange_SmallCapacity"; case ExceptionResource.ArgumentOutOfRange_Index: return "ArgumentOutOfRange_Index"; case ExceptionResource.Argument_InvalidOffLen: return "Argument_InvalidOffLen"; case ExceptionResource.Argument_ItemNotExist: return "Argument_ItemNotExist"; case ExceptionResource.ArgumentOutOfRange_Count: return "ArgumentOutOfRange_Count"; case ExceptionResource.ArgumentOutOfRange_InvalidThreshold: return "ArgumentOutOfRange_InvalidThreshold"; case ExceptionResource.ArgumentOutOfRange_ListInsert: return "ArgumentOutOfRange_ListInsert"; case ExceptionResource.NotSupported_ReadOnlyCollection: return "NotSupported_ReadOnlyCollection"; case ExceptionResource.InvalidOperation_CannotRemoveFromStackOrQueue: return "InvalidOperation_CannotRemoveFromStackOrQueue"; case ExceptionResource.InvalidOperation_EmptyQueue: return "InvalidOperation_EmptyQueue"; case ExceptionResource.InvalidOperation_EnumOpCantHappen: return "InvalidOperation_EnumOpCantHappen"; case ExceptionResource.InvalidOperation_EnumFailedVersion: return "InvalidOperation_EnumFailedVersion"; case ExceptionResource.InvalidOperation_EmptyStack: return "InvalidOperation_EmptyStack"; case ExceptionResource.ArgumentOutOfRange_BiggerThanCollection: return "ArgumentOutOfRange_BiggerThanCollection"; case ExceptionResource.InvalidOperation_EnumNotStarted: return "InvalidOperation_EnumNotStarted"; case ExceptionResource.InvalidOperation_EnumEnded: return "InvalidOperation_EnumEnded"; case ExceptionResource.NotSupported_SortedListNestedWrite: return "NotSupported_SortedListNestedWrite"; case ExceptionResource.InvalidOperation_NoValue: return "InvalidOperation_NoValue"; case ExceptionResource.InvalidOperation_RegRemoveSubKey: return "InvalidOperation_RegRemoveSubKey"; case ExceptionResource.Security_RegistryPermission: return "Security_RegistryPermission"; case ExceptionResource.UnauthorizedAccess_RegistryNoWrite: return "UnauthorizedAccess_RegistryNoWrite"; case ExceptionResource.ObjectDisposed_RegKeyClosed: return "ObjectDisposed_RegKeyClosed"; case ExceptionResource.NotSupported_InComparableType: return "NotSupported_InComparableType"; default: return string.Empty; } } } } ================================================ FILE: SGFCore/Utils/TimeUtils.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * TimeUtils * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; namespace SGF.Utils { public class TimeUtils { readonly static DateTime DateTime_1970_01_01_08_00_00 = new DateTime(1970, 1, 1, 8, 0, 0); //自 1970 年 1 月 1 日午夜 12:00:00 经过的毫秒数 public static double GetTotalMillisecondsSince1970() { DateTime nowtime = DateTime.Now.ToLocalTime(); return nowtime.Subtract(DateTime_1970_01_01_08_00_00).TotalMilliseconds; } public static double GetTotalSecondsSince1970() { DateTime nowtime = DateTime.Now.ToLocalTime(); return nowtime.Subtract(DateTime_1970_01_01_08_00_00).TotalSeconds; } public static TimeSpan GetTimeSpanSince1970() { return DateTime.Now.Subtract(DateTime_1970_01_01_08_00_00); } public static string FormatShowTime(ulong timeInSec) { string _text = ""; ulong showTime; if ((timeInSec / (ulong)86400) > 0) { showTime = timeInSec / (ulong)86400; _text = showTime.ToString() + "天"; } else if ((timeInSec / (ulong)3600) > 0) { showTime = timeInSec / (ulong)3600; _text = showTime.ToString() + "小时"; } else if ((timeInSec / (ulong)60) > 0) { showTime = timeInSec / (ulong)60; _text = showTime.ToString() + "分钟"; } else { // 对1分钟进行特殊处理, 30秒 和 1分30秒 均为1分钟 _text = "1分钟"; } return _text; } //-------------------------------------------------------------------------------- public const uint OnDaySecond = 24 * 60 * 60; public const uint OnHourSecond = 60 * 60; public static string GetTimeString(string format, long seconds) { string label = format; int ms = (int)(seconds * 1000); int s = (int)seconds; int m = s / 60; int h = m / 60; int d = h / 24; string t = ""; //处理天 if (label.IndexOf("%dd") >= 0) { t = d >= 10 ? d.ToString() : ("0" + d.ToString()); label = label.Replace("%dd", t); h = h % 24; } else if (label.IndexOf("%d") >= 0) { label = label.Replace("%d", d.ToString()); h = h % 24; } //处理小时 if (label.IndexOf("%hh") >= 0) { t = h >= 10 ? h.ToString() : ("0" + h.ToString()); label = label.Replace("%hh", t); m = m % 60; } else if (label.IndexOf("%h") >= 0) { label = label.Replace("%h", h.ToString()); m = m % 60; } //处理分 if (label.IndexOf("%mm") >= 0) { t = m >= 10 ? m.ToString() : ("0" + m.ToString()); label = label.Replace("%mm", t); s = s % 60; } else if (label.IndexOf("%m") >= 0) { label = label.Replace("%m", m.ToString()); s = s % 60; } //处理秒 if (label.IndexOf("%ss") >= 0) { t = s >= 10 ? s.ToString() : ("0" + s.ToString()); label = label.Replace("%ss", t); ms = ms % 1000; } else if (label.IndexOf("%s") >= 0) { label = label.Replace("%s", s.ToString()); ms = ms % 1000; } //处理毫秒 if (label.IndexOf("ms") >= 0) { t = ms.ToString(); label = label.Replace("%ms", t); } return label; } /// /// 如果不显示天, 显示hh就会显示所有小时, 但是又怕有地方需要这样, 因此这里新开一下 /// /// /// /// public static string GetTimeStringV2(string format, long seconds) { string label = format; int ms = (int)(seconds * 1000); int s = (int)seconds; int m = s / 60; int h = m / 60; int d = h / 24; string t = ""; //处理天 if (label.IndexOf("%dd") >= 0) { t = d >= 10 ? d.ToString() : ("0" + d.ToString()); label = label.Replace("%dd", t); } else if (label.IndexOf("%d") >= 0) { label = label.Replace("%d", d.ToString()); } h = h % 24; //处理小时 if (label.IndexOf("%hh") >= 0) { t = h >= 10 ? h.ToString() : ("0" + h.ToString()); label = label.Replace("%hh", t); } else if (label.IndexOf("%h") >= 0) { label = label.Replace("%h", h.ToString()); } m = m % 60; //处理分 if (label.IndexOf("%mm") >= 0) { t = m >= 10 ? m.ToString() : ("0" + m.ToString()); label = label.Replace("%mm", t); } else if (label.IndexOf("%m") >= 0) { label = label.Replace("%m", m.ToString()); } s = s % 60; //处理秒 if (label.IndexOf("%ss") >= 0) { t = s >= 10 ? s.ToString() : ("0" + s.ToString()); label = label.Replace("%ss", t); } else if (label.IndexOf("%s") >= 0) { label = label.Replace("%s", s.ToString()); } ms = ms % 1000; //处理毫秒 if (label.IndexOf("ms") >= 0) { t = ms.ToString(); label = label.Replace("%ms", t); } return label; } public static DateTime GetLocalTime(uint timeStamp) { DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); long lTime = long.Parse(timeStamp + "0000000"); TimeSpan toNow = new TimeSpan(lTime); DateTime dtResult = dtStart.Add(toNow); return dtResult; } private static uint DAY_PER_YEAR = 365; private static uint DAY_PER_MONTH = 30; private static uint DAY_PER_WEEK = 7; public static string DateStringFromNow(DateTime dt) { TimeSpan span = DateTime.Now - dt; double year = (span.TotalDays / DAY_PER_YEAR); double month = (span.TotalDays / DAY_PER_MONTH); double week = (span.TotalDays / DAY_PER_WEEK); if (year > 1) { return string.Format("{0}年前", (int)System.Math.Floor(year)); } else if (month > 1) { return string.Format("{0}个月前", (int)System.Math.Floor(month)); } else if (week > 1) { return string.Format("{0}周前", (int)System.Math.Floor(week)); } else if (span.TotalDays > 1) { return string.Format("{0}天前", (int)System.Math.Floor(span.TotalDays)); } else if (span.TotalHours > 1) { return string.Format("{0}小时前", (int)System.Math.Floor(span.TotalHours)); } else if (span.TotalMinutes > 1) { return string.Format("{0}分钟前", (int)System.Math.Floor(span.TotalMinutes)); } else { return //string.Format("{0}秒前", (int)Math.Floor(span.TotalSeconds)); "刚才"; } } public static double GetMillisecondsFromTicks(long ticks) { return ticks / 10000.0f; } public static double GetSecondsFromTicks(long ticks) { return (ticks / 10000.0f)/1000.0f; } } } ================================================ FILE: SGFCore/Utils/URLUtils.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * UrlUtils * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ namespace SGF.Utils { public class UrlUtils { public const string TAG = "UrlUtils"; public static readonly string[] UrlHeadDefine = { "http://", "https://" }; //已经单元测试通过 public static void SplitUrl(string url, out string head, out string host, out string port, out string path) { int a = url.IndexOf("://"); if (a >= 0) { head = url.Substring(0, a + 3); url = url.Substring(a + 3); } else { head = ""; } a = url.IndexOf("/"); if (a >= 0) { host = url.Substring(0, a); path = url.Substring(a); } else { host = url; path = ""; } a = host.LastIndexOf(":"); if (a >= 0) { port = host.Substring(a + 1); host = host.Substring(0, a); } else { port = ""; } Debuger.Log("URLUtils", "SplitUrl() head=" + head + ", host=" + host + ", port=" + port + ", path=" + path); } } } ================================================ FILE: SGFCoreTest/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // 有关程序集的一般信息由以下 // 控制。更改这些特性值可修改 // 与程序集关联的信息。 [assembly: AssemblyTitle("SGFCoreTest")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("SGFCoreTest")] [assembly: AssemblyCopyright("Copyright © 2018")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] //将 ComVisible 设置为 false 将使此程序集中的类型 //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, //请将此类型的 ComVisible 特性设置为 true。 [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID [assembly: Guid("429de438-82f6-4e6a-a6d1-9d5b3010c893")] // 程序集的版本信息由下列四个值组成: // // 主版本 // 次版本 // 生成号 // 修订号 // //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, // 方法是按如下所示使用“*”: : // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: SGFCoreTest/SGFCoreTest.csproj ================================================  Debug AnyCPU {429DE438-82F6-4E6A-A6D1-9D5B3010C893} Library Properties SGFCoreTest SGFCoreTest v4.0 512 {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages False UnitTest true full false bin\Debug\ DEBUG;TRACE prompt 4 pdbonly true bin\Release\ TRACE prompt 4 3.5 False {eeb72dfc-0fa5-44de-b75a-586f69377aa6} SGFCore False False False False ================================================ FILE: SGFCoreTest/TestMarshalArray.cs ================================================ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; using SGF.G3Lite; using SGF.Marshals; namespace SGFCoreTest { [TestClass] public class TestMarshalArray { [TestCleanup] public void Cleanup() { MarshalArrayBase.Cleanup(); } [TestMethod] public void TestSetterGetterInt() { int count = 100; MarshalArray list = new MarshalArray(count); Assert.AreEqual(list.Length, count); for (int i = 0; i < count; i++) { list[i] = i; } Assert.AreEqual(list.Length, count); for (int i = 0; i < count; i++) { Assert.AreEqual(list[i], i); } } [TestMethod] public void TestSetterGetterFloat() { int count = 100; MarshalArray list = new MarshalArray(count); Assert.AreEqual(list.Length, count); for (int i = 0; i < count; i++) { list[i] = i; } Assert.AreEqual(list.Length, count); for (int i = 0; i < count; i++) { Assert.AreEqual(list[i], i); } } [TestMethod] public void TestSetterGetterVector() { int count = 100; MarshalArray list = new MarshalArray(count); Assert.AreEqual(list.Length, count); for (int i = 0; i < count; i++) { list[i] = new Vector3(i, i, i); } Assert.AreEqual(list.Length, count); for (int i = 0; i < count; i++) { Assert.AreEqual(list[i], new Vector3(i, i, i)); } } [TestMethod] public void TestIndexOf() { int count = 100; MarshalArray list = new MarshalArray(count); Assert.AreEqual(list.Length, count); for (int i = 0; i < count; i++) { list[i] = new Vector3(i, i, i); } int result = -1; result = MarshalArrayBase.IndexOf(list, new Vector3(5, 5, 5), 0, list.Length); Assert.AreEqual(result, 5); result = MarshalArrayBase.IndexOf(list, new Vector3(5, 5, 5), 5, list.Length); Assert.AreEqual(result, 5); result = MarshalArrayBase.IndexOf(list, new Vector3(5, 5, 5), 6, list.Length); Assert.AreEqual(result, -1); result = MarshalArrayBase.IndexOf(list, new Vector3(5, 5, 5), 5, 1); Assert.AreEqual(result, 5); result = MarshalArrayBase.IndexOf(list, new Vector3(5, 5, 5), 5, 0); Assert.AreEqual(result, -1); result = MarshalArrayBase.IndexOf(list, new Vector3(5, 5, 5), 0, 6); Assert.AreEqual(result, 5); result = MarshalArrayBase.IndexOf(list, new Vector3(5, 5, 5), 0, 3); Assert.AreEqual(result, -1); } [TestMethod] public void TestLastIndexOf() { int count = 100; MarshalArray list = new MarshalArray(count); Assert.AreEqual(list.Length, count); for (int i = 0; i < count; i++) { list[i] = new Vector3(i, i, i); } int result = -1; result = MarshalArrayBase.LastIndexOf(list, new Vector3(5, 5, 5), 0, list.Length); Assert.AreEqual(result, -1); result = MarshalArrayBase.LastIndexOf(list, new Vector3(5, 5, 5), 5, list.Length); Assert.AreEqual(result, 5); result = MarshalArrayBase.LastIndexOf(list, new Vector3(5, 5, 5), 6, list.Length); Assert.AreEqual(result, 5); result = MarshalArrayBase.LastIndexOf(list, new Vector3(5, 5, 5), 5, 1); Assert.AreEqual(result, 5); result = MarshalArrayBase.LastIndexOf(list, new Vector3(5, 5, 5), 5, 0); Assert.AreEqual(result, -1); result = MarshalArrayBase.LastIndexOf(list, new Vector3(5, 5, 5), 0, 6); Assert.AreEqual(result, -1); result = MarshalArrayBase.LastIndexOf(list, new Vector3(5, 5, 5), 0, 3); Assert.AreEqual(result, -1); } [TestMethod] public void TestCopyMarshal2Marshal() { int count = 100; MarshalArray list = new MarshalArray(count); Assert.AreEqual(list.Length, count); for (int i = 0; i < count; i++) { list[i] = new Vector3(i, i, i); } MarshalArray list2 = new MarshalArray(count); MarshalArrayBase.Copy(list, 0, list2, 0, count); Assert.AreEqual(list2.Length, count); for (int i = 0; i < count; i++) { Assert.AreEqual(list2[i], new Vector3(i, i, i)); } MarshalArray list3 = new MarshalArray(10); MarshalArrayBase.Copy(list2, 10, list3, 5, 10); Assert.AreEqual(list3[5], new Vector3(10, 10, 10)); Assert.AreEqual(list3[9], new Vector3(14, 14, 14)); } [TestMethod] public void TestCopyManaged2Marshal() { int count = 100; MarshalArray list = new MarshalArray(count); Assert.AreEqual(list.Length, count); for (int i = 0; i < count; i++) { list[i] = new Vector3(i, i, i); } Vector3[] list2 = new Vector3[count]; MarshalArrayBase.Copy(list, 0, list2, 0, count); Assert.AreEqual(list2.Length, count); for (int i = 0; i < count; i++) { Assert.AreEqual(list2[i], new Vector3(i, i, i)); } MarshalArray list3 = new MarshalArray(10); MarshalArrayBase.Copy(list2, 10, list3, 5, 10); Assert.AreEqual(list3[5], new Vector3(10, 10, 10)); Assert.AreEqual(list3[9], new Vector3(14, 14, 14)); } [TestMethod] public void TestCopyIntPtr2IntPtr() { int count = 100; MarshalArray list = new MarshalArray(count); Assert.AreEqual(list.Length, count); for (int i = 0; i < count; i++) { list[i] = new Vector3(i, i, i); } MarshalArray list2 = new MarshalArray(count); MarshalArrayBase.CopyBytes(list.Ptr, list.ElementSize, list2.Ptr, 0, list.ByteLength); Assert.AreEqual(list2.Length, count); for (int i = 0; i < count - 1; i++) { Assert.AreEqual(list2[i], new Vector3(i + 1, i + 1, i + 1)); } } [TestMethod] public void TestForEach() { int count = 100; MarshalArray list = new MarshalArray(count); Assert.AreEqual(list.Length, count); for (int i = 0; i < count; i++) { list[i] = new Vector3(i, i, i); } int j = 0; foreach (var vector3 in list) { Assert.AreEqual(vector3, new Vector3(j, j, j)); j++; } } } } ================================================ FILE: SGFCoreTest/TestMarshalList.cs ================================================ using System; using System.Collections.Generic; using Microsoft.VisualStudio.TestTools.UnitTesting; using SGF.Marshals; namespace SGFCoreTest { [TestClass] public class TestMarshalList { [TestCleanup] public void Cleanup() { MarshalArrayBase.Cleanup(); } [TestMethod] public void TestAdd() { MarshalList list = new MarshalList(); Assert.AreEqual(list.Capacity, 4); Assert.AreEqual(list.Count, 0); for (int i = 0; i < 10; i++) { list.Add(i); } Assert.AreEqual(list.Count, 10); Assert.AreEqual(list.Capacity, 16); for (int i = 0; i < 10; i++) { Assert.AreEqual(list[i], i); } } [TestMethod] public void TestAddRange() { MarshalList list = new MarshalList(); for (int i = 0; i < 100; i++) { list.Add(i); } MarshalList list2 = new MarshalList(); list2.AddRange(list); Assert.AreEqual(list2.Count, 100); for (int i = 0; i < 100; i++) { Assert.AreEqual(list2[i], i); } list2.AddRange(list); Assert.AreEqual(list2.Count, 200); for (int i = 100; i < 200; i++) { Assert.AreEqual(list2[i], i - 100); } list2.AddRange(list2); Assert.AreEqual(list2.Count, 400); for (int i = 200; i < 300; i++) { Assert.AreEqual(list2[i], i - 200); } int[] list3 = new int[100]; for (int i = 0; i < 100; i++) { list3[i] = 10000 + i; } list.AddRange(list3); for (int i = 100; i < 200; i++) { Assert.AreEqual(list[i], 10000 + i - 100); } List list4 = new List(); list4.AddRange(list3); list.AddRange(list4); for (int i = 200; i < 300; i++) { Assert.AreEqual(list[i], 10000 + i - 200); } } [TestMethod] public void TestInsert() { MarshalList list = new MarshalList(); for (int i = 0; i < 100; i++) { list.Add(i); } list.Insert(100, 10001); list.Insert(100, 10002); Assert.AreEqual(list.Count, 102); Assert.AreEqual(list[100], 10002); Assert.AreEqual(list[101], 10001); list.Insert(0, 10003); Assert.AreEqual(list[0], 10003); Assert.AreEqual(list[1], 0); Assert.AreEqual(list[2], 1); Assert.AreEqual(list[99], 98); Assert.AreEqual(list[102], 10001); } [TestMethod] public void TestRemove() { MarshalList list = new MarshalList(); for (int i = 0; i < 100; i++) { list.Add(i); } Assert.AreEqual(list.Remove(2), true); Assert.AreEqual(list.Count, 99); Assert.AreEqual(list[2], 3); Assert.AreEqual(list.Remove(2), false); list.RemoveAt(0); Assert.AreEqual(list[0], 1); list.RemoveAt(97); Assert.AreEqual(list.Count, 97); list.RemoveRange(0, 96); Assert.AreEqual(list.Count, 1); Assert.AreEqual(list[0], 98); } [TestMethod] public void TestContains() { MarshalList list = new MarshalList(); for (int i = 0; i < 100; i++) { list.Add(i); } Assert.AreEqual(list.Contains(5), true); Assert.AreEqual(list.Contains(500), false); } [TestMethod] public void TestCopyToManagedArray() { MarshalList list = new MarshalList(); for (int i = 0; i < 100; i++) { list.Add(i); } int[] list1 = new int[100]; list.CopyTo((Array)list1, 0); for (int i = 0; i < 100; i++) { Assert.AreEqual(list1[i], i); } } [TestMethod] public void TestForEach() { MarshalList list = new MarshalList(); for (int i = 0; i < 100; i++) { list.Add(i); } int j = 0; foreach (var i in list) { Assert.AreEqual(i, j); ++j; } } [TestMethod] public void TestGetRange() { MarshalList list = new MarshalList(); for (int i = 0; i < 100; i++) { list.Add(i); } var list1 = list.GetRange(50, 50); Assert.AreEqual(list1.Count, 50); for (int i = 0; i < 50; i++) { Assert.AreEqual(list1[i], i + 50); } } } } ================================================ FILE: SGFDebuger/Debuger.cs ================================================ //////////////////////////////////////////////////////////////////// // _ooOoo_ // // o8888888o // // 88" . "88 // // (| ^_^ |) // // O\ = /O // // ____/`---'\____ // // .' \\| |// `. // // / \\||| : |||// \ // // / _||||| -:- |||||- \ // // | | \\\ - /// | | // // | \_| ''\---/'' | | // // \ .-\__ `-` ___/-. / // // ___`. .' /--.--\ `. . ___ // // ."" '< `.___\_<|>_/___.' >'"". // // | | : `- \`.;`\ _ /`;.`/ - ` : | | // // \ \ `-. \_ __\ /__ _/ .-` / / // // ========`-.____`-.___\_____/___.-`____.-'======== // // `=---=' // // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // // 佛祖保佑 无BUG 不修改 // //////////////////////////////////////////////////////////////////// /* * 描述: * 作者:slicol */ using System; using System.Diagnostics; using System.IO; using System.Reflection; namespace SGF { public interface IDebugerConsole { void Log(string msg, object context = null); void LogWarning(string msg, object context = null); void LogError(string msg, object context = null); } public class UnityDebugerConsole : IDebugerConsole { private object[] m_tmpArgs = new[] { "" }; private MethodInfo m_miLog; private MethodInfo m_miLogWarning; private MethodInfo m_miLogError; public UnityDebugerConsole() { Type type = Type.GetType("UnityEngine.Debug, UnityEngine"); m_miLog = type.GetMethod("Log", new Type[] { typeof(object) }); m_miLogWarning = type.GetMethod("LogWarning", new Type[] { typeof(object) }); m_miLogError = type.GetMethod("LogError", new Type[] { typeof(object) }); } public void Log(string msg, object context = null) { m_tmpArgs[0] = msg; m_miLog.Invoke(null, m_tmpArgs); } public void LogWarning(string msg, object context = null) { m_tmpArgs[0] = msg; m_miLogWarning.Invoke(null, m_tmpArgs); } public void LogError(string msg, object context = null) { m_tmpArgs[0] = msg; m_miLogError.Invoke(null, m_tmpArgs); } } public class SystemColorConsole : IDebugerConsole { public void Log(string msg, object context = null) { Console.WriteLine(msg); } public void LogWarning(string msg, object context = null) { var old = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine(msg); Console.ForegroundColor = old; } public void LogError(string msg, object context = null) { var old = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(msg); Console.ForegroundColor = old; } } public interface ILogTag { string LOG_TAG { get; } } public static class Debuger { public static bool EnableLog = true; public static bool EnableLogVerbose = false; public static bool EnableTime = true; public static bool EnableDate = false; public static bool EnableSave = false; public static bool EnableStack = false; public static bool EnableErrorStack = true; public static string LogFileDir = ""; public static string LogFileName = ""; public static string Prefix = "> "; public static StreamWriter LogFileWriter = null; private static IDebugerConsole m_console; public static void Init(string logFileDir = null, IDebugerConsole console = null) { LogFileDir = logFileDir; m_console = console; if (string.IsNullOrEmpty(LogFileDir)) { string path = System.AppDomain.CurrentDomain.BaseDirectory; LogFileDir = path + "/DebugerLog/"; } } public static void Internal_Log(string msg, object context = null) { if (m_console != null) { m_console.Log(msg, context); } else { Console.WriteLine(msg); } } public static void Internal_LogWarning(string msg, object context = null) { if (m_console != null) { m_console.LogWarning(msg, context); } else { Console.WriteLine(msg); } } public static void Internal_LogError(string msg, object context = null) { if (m_console != null) { m_console.LogError(msg, context); } else { Console.WriteLine(msg); } } #region ////Log(...)//// //---------------------------------------------------------------------- //Log //---------------------------------------------------------------------- public static void Log(string message = "") { if (!Debuger.EnableLog) { return; } message = GetLogText(GetLogCaller(true), message); Internal_Log(Prefix + message); LogToFile("[I]" + message); } public static void Log(object message) { if (!Debuger.EnableLog) { return; } message = GetLogText(GetLogCaller(true), message.ToString()); Internal_Log(Prefix + message); LogToFile("[I]" + message); } public static void Log(string format, params object[] args) { if (!Debuger.EnableLog) { return; } string message = GetLogText(GetLogCaller(true), string.Format(format, args)); Internal_Log(Prefix + message); LogToFile("[I]" + message); } public static void Log(this ILogTag obj, string message = "") { if (!Debuger.EnableLog) { return; } message = GetLogText(GetLogTag(obj), GetLogCaller(), message); Internal_Log(Prefix + message); LogToFile("[I]" + message); } public static void Log(this ILogTag obj, string format, params object[] args) { if (!Debuger.EnableLog) { return; } string message = GetLogText(GetLogTag(obj), GetLogCaller(), string.Format(format, args)); Internal_Log(Prefix + message); LogToFile("[I]" + message); } //---------------------------------------------------------------------- //LogVerbose //---------------------------------------------------------------------- [Conditional("ENABLE_LOG")] public static void LogVerbose(string message = "") { if (!EnableLog || !EnableLogVerbose) { return; } message = GetLogText(GetLogCaller(true), message); Internal_Log(Prefix + message); LogToFile("[I]" + message); } [Conditional("ENABLE_LOG")] public static void LogVerbose(object message) { if (!EnableLog || !EnableLogVerbose) { return; } message = GetLogText(GetLogCaller(true), message.ToString()); Internal_Log(Prefix + message); LogToFile("[I]" + message); } [Conditional("ENABLE_LOG")] public static void LogVerbose(string format, params object[] args) { if (!EnableLog || !EnableLogVerbose) { return; } string message = GetLogText(GetLogCaller(true), string.Format(format, args)); Internal_Log(Prefix + message); LogToFile("[I]" + message); } [Conditional("ENABLE_LOG")] public static void LogVerbose(this ILogTag obj, string message = "") { if (!EnableLog || !EnableLogVerbose) { return; } message = GetLogText(GetLogTag(obj), GetLogCaller(), message); Internal_Log(Prefix + message); LogToFile("[I]" + message); } [Conditional("ENABLE_LOG")] public static void LogVerbose(this ILogTag obj, string format, params object[] args) { if (!EnableLog || !EnableLogVerbose) { return; } string message = GetLogText(GetLogTag(obj), GetLogCaller(), string.Format(format, args)); Internal_Log(Prefix + message); LogToFile("[I]" + message); } //---------------------------------------------------------------------- //LogWarning //---------------------------------------------------------------------- public static void LogWarning(string message) { message = GetLogText(GetLogCaller(true), message); Internal_LogWarning(Prefix + message); LogToFile("[W]" + message); } public static void LogWarning(object message) { message = GetLogText(GetLogCaller(true), message.ToString()); Internal_LogWarning(Prefix + message); LogToFile("[W]" + message); } public static void LogWarning(string format, params object[] args) { string message = GetLogText(GetLogCaller(true), string.Format(format, args)); Internal_LogWarning(Prefix + message); LogToFile("[W]" + message); } public static void LogWarning(this ILogTag obj, string message) { message = GetLogText(GetLogTag(obj), GetLogCaller(), message); Internal_LogWarning(Prefix + message); LogToFile("[W]" + message); } public static void LogWarning(this ILogTag obj, string format, params object[] args) { string message = GetLogText(GetLogTag(obj), GetLogCaller(), string.Format(format, args)); Internal_LogWarning(Prefix + message); LogToFile("[W]" + message); } //---------------------------------------------------------------------- //LogWarning //---------------------------------------------------------------------- public static void LogError(string message) { message = GetLogText(GetLogCaller(true), message); Internal_LogError(Prefix + message); LogToFile("[E]" + message, EnableErrorStack); } public static void LogError(object message) { message = GetLogText(GetLogCaller(true), message.ToString()); Internal_LogError(Prefix + message); LogToFile("[E]" + message, EnableErrorStack); } public static void LogError(string format, params object[] args) { string message = GetLogText(GetLogCaller(true), string.Format(format, args)); Internal_LogError(Prefix + message); LogToFile("[E]" + message, EnableErrorStack); } public static void LogError(this ILogTag obj, string message) { message = GetLogText(GetLogTag(obj), GetLogCaller(), message); Internal_LogError(Prefix + message); LogToFile("[E]" + message, EnableErrorStack); } public static void LogError(this ILogTag obj, string format, params object[] args) { string message = GetLogText(GetLogTag(obj), GetLogCaller(), string.Format(format, args)); Internal_LogError(Prefix + message); LogToFile("[E]" + message, EnableErrorStack); } #endregion //---------------------------------------------------------------------- //工具函数 //---------------------------------------------------------------------- private static string GetLogText(string tag, string methodName, string message) { string str = ""; if (Debuger.EnableDate) { DateTime now = DateTime.Now; str = now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " "; } else if (Debuger.EnableTime) { DateTime now = DateTime.Now; str = now.ToString("HH:mm:ss.fff") + " "; } str = str + tag + "::" + methodName + "() " + message; return str; } private static string GetLogText(string caller, string message) { string str = ""; if (Debuger.EnableDate) { DateTime now = DateTime.Now; str = now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " "; } else if (Debuger.EnableTime) { DateTime now = DateTime.Now; str = now.ToString("HH:mm:ss.fff") + " "; } str = str + caller + "() " + message; return str; } private static string GetLogTag(ILogTag obj) { return obj.LOG_TAG; /* ILogTag tag = obj as ILogTag; if (tag != null) { return tag.LOG_TAG; } return obj.GetType().Name; */ } private static Assembly ms_Assembly; private static string GetLogCaller(bool bIncludeClassName = false) { StackTrace st = new StackTrace(2, false); if (st != null) { if (null == ms_Assembly) { ms_Assembly = typeof(Debuger).Assembly; } int currStackFrameIndex = 0; while (currStackFrameIndex < st.FrameCount) { StackFrame oneSf = st.GetFrame(currStackFrameIndex); MethodBase oneMethod = oneSf.GetMethod(); if (oneMethod.Module.Assembly != ms_Assembly) { if (bIncludeClassName) { return oneMethod.DeclaringType.Name + "::" + oneMethod.Name; } else { return oneMethod.Name; } } currStackFrameIndex++; } } return ""; } //---------------------------------------------------------------------- public static string CheckLogFileDir() { if (string.IsNullOrEmpty(LogFileDir)) { Internal_LogError("Debuger::CheckLogFileDir() LogFileDir is NULL!"); return ""; } try { if (!Directory.Exists(LogFileDir)) { Directory.CreateDirectory(LogFileDir); } } catch (Exception e) { Internal_LogError("Debuger::CheckLogFileDir() " + e.Message + e.StackTrace); return ""; } return LogFileDir; } public static string GenLogFileName() { DateTime now = DateTime.Now; string filename = now.GetDateTimeFormats('s')[0].ToString();//2005-11-05T14:06:25 filename = filename.Replace("-", "_"); filename = filename.Replace(":", "_"); filename = filename.Replace(" ", ""); filename += ".log"; return filename; } private static void LogToFile(string message, bool EnableStack = false) { if (!EnableSave) { return; } if (LogFileWriter == null) { LogFileName = GenLogFileName(); LogFileDir = CheckLogFileDir(); if (string.IsNullOrEmpty(LogFileDir)) { return; } string fullpath = LogFileDir + LogFileName; try { LogFileWriter = File.AppendText(fullpath); LogFileWriter.AutoFlush = true; } catch (Exception e) { LogFileWriter = null; Internal_LogError("Debuger::LogToFile() " + e.Message + e.StackTrace); return; } } if (LogFileWriter != null) { try { LogFileWriter.WriteLine(message); if ((EnableStack || Debuger.EnableStack)) { StackTrace st = new StackTrace(2, false); LogFileWriter.WriteLine(st.ToString()); } } catch (Exception) { return; } } } } } ================================================ FILE: SGFDebuger/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // 有关程序集的一般信息由以下 // 控制。更改这些特性值可修改 // 与程序集关联的信息。 [assembly: AssemblyTitle("Debuger")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Microsoft")] [assembly: AssemblyProduct("Debuger")] [assembly: AssemblyCopyright("Copyright © Microsoft 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] //将 ComVisible 设置为 false 将使此程序集中的类型 //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, //请将此类型的 ComVisible 特性设置为 true。 [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID [assembly: Guid("dc1d8b0a-9c8c-4911-aafe-d7d958ec4044")] // 程序集的版本信息由下列四个值组成: // // 主版本 // 次版本 // 生成号 // 修订号 // //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, // 方法是按如下所示使用“*”: : // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: SGFDebuger/SGFDebuger.csproj ================================================  Debug AnyCPU {DC1D8B0A-9C8C-4911-AAFE-D7D958EC4044} Library Properties SGF.Debuger SGFDebuger v3.5 512 true full false ..\Libs\ TRACE;DEBUG;ENABLE_LOG;ENABLE_LOG_LOOP prompt 4 pdbonly true ..\Libs\ TRACE;ENABLE_LOG;ENABLE_LOG_LOOP prompt 4 $(ProjectDir)..\Libs\PublishLibrary.bat $(TargetName) ================================================ FILE: SGFServerLite/App.config ================================================ ================================================ FILE: SGFServerLite/GameServer/GameServer.cs ================================================ using SGF.IPCWork; using SGF.Network.General; using SGF.Network.General.Server; using SGF.Server; namespace SGFServerDemo.GameServer { public class GameServer:ServerModule { private NetManager m_net; private IPCManager m_ipc; public override void Start() { base.Start(); m_net = new NetManager(); m_net.Init(ConnectionType.RUDP, 2939); m_ipc = new IPCManager(); m_ipc.Init(id); } public override void Tick() { m_net.Tick(); m_ipc.Tick(); } } } ================================================ FILE: SGFServerLite/Program.cs ================================================ using System; using SGF; using SGF.Server; using SGF.Time; using SGFServerDemo.ZoneServer; namespace SGFServerDemo { class Program { public const int SVR_ZONE = 1; public const int SVR_GAME = 1; static void Main(string[] args) { InitDebuger(); SGFTime.DateTimeAppStart = DateTime.Now; ServerManager.Instance.StartServer(SVR_ZONE); ServerManager.Instance.StartServer(SVR_GAME); MainLoop.Run(); ServerManager.Instance.StopAllServer(); Console.WriteLine("GameOver"); Console.ReadKey(); } private static void InitDebuger() { Debuger.Init(AppDomain.CurrentDomain.BaseDirectory + "/ServerLog/"); Debuger.EnableLog = false; Debuger.EnableSave = true; Debuger.Log(); } } } ================================================ FILE: SGFServerLite/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // 有关程序集的一般信息由以下 // 控制。更改这些特性值可修改 // 与程序集关联的信息。 [assembly: AssemblyTitle("SGFServerLite")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("HP Inc.")] [assembly: AssemblyProduct("SGFServerLite")] [assembly: AssemblyCopyright("Copyright © HP Inc. 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // 将 ComVisible 设置为 false 会使此程序集中的类型 //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 //请将此类型的 ComVisible 特性设置为 true。 [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID [assembly: Guid("d1acc88b-2b6e-43e5-8314-dd64c2f25aa7")] // 程序集的版本信息由下列四个值组成: // // 主版本 // 次版本 // 生成号 // 修订号 // // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 // 方法是按如下所示使用“*”: : // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: SGFServerLite/SGFServerDemo.csproj ================================================  Debug AnyCPU {D1ACC88B-2B6E-43E5-8314-DD64C2F25AA7} Exe SGFServerDemo SGFServerDemo v3.5 512 true AnyCPU true full false ..\Apps\ TRACE;DEBUG;ENABLE_LOG prompt 4 AnyCPU pdbonly true ..\Apps\ TRACE prompt 4 False ..\Libs\Common\protobuf-net.dll {a1bf1b00-7cdf-4a48-8d33-98645e5df606} SGFAppCommon {eeb72dfc-0fa5-44de-b75a-586f69377aa6} SGFCore {dc1d8b0a-9c8c-4911-aafe-d7d958ec4044} SGFDebuger ================================================ FILE: SGFServerLite/ZoneServer/Online/OnlineManager.cs ================================================ using System.Diagnostics; using System.Text; using SGF; using SGF.Network.Core; using SGF.Network.Core.RPCLite; using SGF.Network.General.Proto; using SGF.Network.General.Server; using SGF.Time; using SGF.Utils; using SGFAppDemo.Common.Data; using SGFAppDemo.Common.Proto; namespace SGFServerDemo.ZoneServer { /// /// 因为只是一个Demo,所以不需要注册,谁先Login,谁先占用UserName /// 如果玩家掉线后,有别的玩家使用该UserName登录,则UserName会被别的玩家占用 /// public class OnlineManager:Singleton { private MapList m_mapUserData; private NetManager m_net; private uint m_lastCheckTimeoutStamp; public void Init(ServerContext context) { m_net = context.net; m_net.SetAuthCmd(ProtoCmd.LoginReq); m_net.AddListener(ProtoCmd.LoginReq, OnLoginRequest); m_net.AddListener(ProtoCmd.HeartBeatReq, OnHeartBeatRequest); m_net.Rpc.RegisterListener(this); m_mapUserData = new MapList(); } public void Dump() { StringBuilder sb = new StringBuilder(); UserData[] list = m_mapUserData.ToArray(); for (int i = 0; i < list.Length; i++) { sb.AppendLine("\t" + list[i].ToString()); } Debuger.LogWarning("\nUser ({0}):\n{1}", m_mapUserData.Count, sb); } private void OnLoginRequest(ISession session, ProtocolHead head, LoginReq req) { Debuger.Log("session:{0}, index:{1}, name:{2}", session.Id, head.index, req.name); bool success = false; UserData ud = GetUserData(req.name); if (ud == null) { //正常登录 //这里简单地使用SessionId作为UserId ud = CreateUserData(session.Id, req.name); ud.svrdata.online = true; ud.svrdata.lastHeartBeatTime = (uint)TimeUtils.GetTotalSecondsSince1970(); //session.SetAuth(ud.id); session.AuthToken = ud.id; success = true; } else { if (req.id == ud.id) { //重新登录 ud.svrdata.online = true; ud.svrdata.lastHeartBeatTime = (uint)TimeUtils.GetTotalSecondsSince1970(); //session.SetAuth(ud.id); session.AuthToken = ud.id; success = true; } else { //正常登录,但是尝试占用已有的名字 if (!ud.svrdata.online) { //如果该名字已经离线,则可以占用 ud.svrdata.online = true; ud.svrdata.lastHeartBeatTime = (uint)TimeUtils.GetTotalSecondsSince1970(); //session.SetAuth(ud.id); session.AuthToken = ud.id; success = true; } } } if (success) { LoginRsp rsp = new LoginRsp(); rsp.ret = ReturnCode.Success; rsp.userdata = ud; m_net.Send(session, head, ProtoCmd.LoginRsp, rsp); } else { LoginRsp rsp = new LoginRsp(); rsp.ret = new ReturnCode(1, "名字已经被占用了!"); m_net.Send(session, head, ProtoCmd.LoginRsp, rsp); } } private void OnHeartBeatRequest(ISession session, ProtocolHead head, HeartBeatReq req) { UserData ud = GetUserData(session.Id); if (ud != null) { ud.svrdata.lastHeartBeatTime = (uint)TimeUtils.GetTotalSecondsSince1970(); session.Ping = req.ping; HeartBeatRsp rsp = new HeartBeatRsp(); rsp.ret = ReturnCode.Success; rsp.timestamp = req.timestamp; m_net.Send(session, head, ProtoCmd.HeartBeatRsp, rsp); } else { Debuger.LogWarning("找不到Session 对应的UserData! session:{0}", session); } } [RPCRequest] private void Logout(ISession session) { OnlineManager.Instance.ReleaseUserData(session.Id); m_net.Rpc.Return(); } public UserData CreateUserData(uint id, string name) { UserData data = new UserData(); data.name = name; data.id = id; data.pwd = ""; m_mapUserData.Add(id, data); return data; } public void ReleaseUserData(uint id) { m_mapUserData.Remove(id); } public UserData GetUserData(string name) { int cnt = m_mapUserData.Count; var list = m_mapUserData.AsList(); for (int i = 0; i < cnt; i++) { if (list[i].name == name) { return list[i]; } } return null; } public UserData GetUserData(uint id) { return m_mapUserData[id]; } } } ================================================ FILE: SGFServerLite/ZoneServer/Room/Room.cs ================================================ using System.Collections.Generic; using System.Text; using SGF.Extension; using SGF.Network.FSPLite; using SGF.Network.General.Server; using SGF.Utils; using SGFAppDemo.Common.Data; namespace SGFServerDemo.ZoneServer { public class Room { private static uint ms_lastRid = 0; public static uint NewRoomID() { return ++ms_lastRid; } private RoomData m_data; public RoomData data{get { return m_data; }} private DictionarySafe m_mapSession; public override string ToString() { return string.Format("",m_data, m_mapSession.ToListString()); } public string DumpString(string prefix = "") { StringBuilder sb = new StringBuilder(); sb.AppendFormat("\n", m_data.id, m_data.name, m_data.owner, m_data.players.Count); sb.AppendLine(prefix + "\tPlayerList:"); for (int i = 0; i < m_data.players.Count; i++) { sb.AppendLine(prefix + "\t" + m_data.players[i].ToString()); } sb.AppendLine(prefix + "\tSessionList:"); foreach (var session in m_mapSession) { sb.AppendLine(prefix + "\t" + session.Value.ToString()); } return sb.ToString(); } public void Create(uint userId, string userName, ISession session, string roomName) { m_mapSession = new DictionarySafe(); m_data = new RoomData(); m_data.id = NewRoomID(); m_data.name = roomName; m_data.owner = userId; AddPlayer(userId, userName, session); } public void AddPlayer(uint userId, string userName, ISession session) { PlayerData data = GetPlayerInfoByUserId(userId); if (data == null) { data = new PlayerData(); m_data.players.Add(data); data.id = (uint)m_data.players.Count; data.sid = session.Id; } data.isReady = false; data.userId = userId; data.name = userName; m_mapSession[userId] = session; } public void RemovePlayer(uint userId) { int i = GetPlayerIndexByUserId(userId); if (i >= 0) { m_data.players.RemoveAt(i); } m_mapSession.Remove(userId); if (userId == m_data.owner) { if (m_data.players.Count > 0) { m_data.owner = m_data.players[0].userId; } } } public int GetPlayerCount() { return m_data.players.Count; } private int GetPlayerIndexByUserId(uint userId) { for (int i = 0; i < m_data.players.Count; i++) { if (m_data.players[i].userId == userId) { return i; } } return -1; } private PlayerData GetPlayerInfoByUserId(uint userId) { for (int i = 0; i < m_data.players.Count; i++) { if (m_data.players[i].userId == userId) { return m_data.players[i]; } } return null; } public ISession[] GetSessionList() { List list = new List(); for (int i = 0; i < m_data.players.Count; i++) { uint userId = m_data.players[i].userId; list.Add(m_mapSession[userId]); } return list.ToArray(); } public bool CanStartGame() { if (m_data.players.Count > 1 && IsAllReady()) { return true; } return false; } public bool IsAllReady() { bool isAllReady = true; for (int i = 0; i < m_data.players.Count; i++) { if (!m_data.players[i].isReady) { isAllReady = false; break; } } return isAllReady; } public void SetReady(uint userId, bool value) { var info = GetPlayerInfoByUserId(userId); if (info != null) { info.isReady = value; } } public FSPParam GetGameStartParam() { FSPParam param = new FSPParam(); return param; } } } ================================================ FILE: SGFServerLite/ZoneServer/Room/RoomManager.cs ================================================ using System.Collections.Generic; using System.Text; using SGF; using SGF.Network.Core.RPCLite; using SGF.Network.FSPLite; using SGF.Network.General.Server; using SGF.Utils; using SGFAppDemo.Common.Data; using SGF.Utils; namespace SGFServerDemo.ZoneServer { public class RoomManager:Singleton { private NetManager m_net; private List m_listRoom = new List(); public void Init(ServerContext context) { m_net = context.net; //m_net.RegisterRPCListener(this); m_net.Rpc.RegisterListener(this); } public void Dump() { StringBuilder sb = new StringBuilder(); Room[] list = m_listRoom.ToArray(); for (int i = 0; i < list.Length; i++) { sb.AppendLine("\t" + list[i].DumpString("\t")); } Debuger.LogWarning("\nRooms ({0}):\n{1}", m_listRoom.Count, sb); } [RPCRequest] private void GetRoomList(ISession session) { List list = new List(); for (int i = 0; i < m_listRoom.Count; i++) { list.Add(m_listRoom[i].data); } RoomListData data = new RoomListData(); data.rooms = list; m_net.Rpc.Return(data); } [RPCRequest] private void CreateRoom(ISession session, uint userId, string roomName) { Room room = new Room(); UserData ud = OnlineManager.Instance.GetUserData(userId); room.Create(userId, ud.name, session, roomName); m_listRoom.Add(room); m_net.Rpc.Return(room.data); } [RPCRequest] private void JoinRoom(ISession session, uint userId, uint roomId) { Room room = GetRoom(roomId); if (room != null) { UserData ud = OnlineManager.Instance.GetUserData(userId); room.AddPlayer(userId, ud.name, session); ISession[] listSession = room.GetSessionList(); m_net.Rpc.Invoke(listSession,"NotifyRoomUpdate", room.data); } else { m_net.Rpc.ReturnError("房间不存在", (int)roomId); } } [RPCRequest] private void ExitRoom(ISession session, uint userId, uint roomId) { Room room = GetRoom(roomId); if (room != null) { room.RemovePlayer(userId); if (room.GetPlayerCount() > 0) { ISession[] listSession = room.GetSessionList(); m_net.Rpc.Invoke(listSession, "NotifyRoomUpdate", room.data); } } } [RPCRequest] private void RoomReady(ISession session, uint userId, uint roomId, bool ready) { Room room = GetRoom(roomId); if (room != null) { room.SetReady(userId, ready); ISession[] listSession = room.GetSessionList(); m_net.Rpc.Invoke(listSession, "NotifyRoomUpdate", room.data); } else { m_net.Rpc.ReturnError("房间不存在", (int)roomId); } } [RPCRequest] private void StartGame(ISession session, uint userId, uint roomId) { Room room = GetRoom(roomId); if (room != null) { if (room.data.owner == userId) { if (room.CanStartGame()) { FSPParam param = room.GetGameStartParam(); ISession[] listSession = room.GetSessionList(); m_net.Rpc.Invoke(listSession, "NotifyGameStart", param); } } } else { m_net.Rpc.ReturnError("房间不存在", (int)roomId); } } private Room GetRoom(uint id) { for (int i = 0; i < m_listRoom.Count; i++) { if (m_listRoom[i].data.id == id) { return m_listRoom[i]; } } return null; } } } ================================================ FILE: SGFServerLite/ZoneServer/ServerContext.cs ================================================ using SGF.IPCWork; using SGF.Network.General.Server; namespace SGFServerDemo.ZoneServer { public class ServerContext { public NetManager net; public IPCManager ipc; } } ================================================ FILE: SGFServerLite/ZoneServer/ZoneServer.cs ================================================ using System; using SGF; using SGF.IPCWork; using SGF.Network.General; using SGF.Network.General.Server; using SGF.Server; using SGF.Utils; namespace SGFServerDemo.ZoneServer { public class ZoneServer : ServerModule { private NetManager m_net; private IPCManager m_ipc; private ServerContext m_context; public override void Start() { base.Start(); m_net = new NetManager(); m_net.Init(ConnectionType.RUDP, 4540); m_ipc = new IPCManager(); m_ipc.Init(id); m_context = new ServerContext(); m_context.net = m_net; m_context.ipc = m_ipc; //业务逻辑初始化 OnlineManager.Instance.Init(m_context); RoomManager.Instance.Init(m_context); ConsoleInput.onInputLine.AddListener(OnInputLine); ConsoleInput.onInputKey.AddListener(OnInputKey); } public override void Tick() { m_net.Tick(); m_ipc.Tick(); } private void OnInputKey(ConsoleKey key) { Debuger.Log(key); if (key == ConsoleKey.F1) { m_net.Dump(); } else if (key == ConsoleKey.F2) { OnlineManager.Instance.Dump(); } else if (key == ConsoleKey.F3) { RoomManager.Instance.Dump(); } else if (key == ConsoleKey.F4) { m_net.Dump(); OnlineManager.Instance.Dump(); RoomManager.Instance.Dump(); } } private void OnInputLine(string line) { Debuger.Log(line); if (line == "dump") { m_net.Dump(); OnlineManager.Instance.Dump(); RoomManager.Instance.Dump(); } } } } ================================================ FILE: SGFUnity/Class1.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace SGFUnity { public class Class1 { } } ================================================ FILE: SGFUnity/Common/AppPrefs.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * AppPrefs * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using UnityEngine; namespace SGF.Unity.Common { public class AppPrefs { private static string ms_prefix = ""; public static void Init(string keyPrefix) { ms_prefix = keyPrefix; } public static float GetFloat(string key) { return PlayerPrefs.GetFloat(GetKey(key)); } // public static float GetFloat(string key, float defaultValue) { return PlayerPrefs.GetFloat(GetKey(key), defaultValue); } public static int GetInt(string key) { return PlayerPrefs.GetInt(GetKey(key)); } // public static int GetInt(string key, int defaultValue) { return PlayerPrefs.GetInt(GetKey(key), defaultValue); } // public static string GetString(string key) { return PlayerPrefs.GetString(GetKey(key)); } // public static string GetString(string key, string defaultValue) { return PlayerPrefs.GetString(GetKey(key), defaultValue); } // public static bool HasKey(string key) { return PlayerPrefs.HasKey(GetKey(key)); } // public static void SetFloat(string key, float value) { PlayerPrefs.SetFloat(GetKey(key), value); } // public static void SetInt(string key, int value) { PlayerPrefs.SetInt(GetKey(key), value); } // public static void SetString(string key, string value) { PlayerPrefs.SetString(GetKey(key), value); } public static void DeleteAll() { PlayerPrefs.DeleteAll(); } // public static void DeleteKey(string key) { PlayerPrefs.DeleteKey(key); } public static void Save() { PlayerPrefs.Save(); } public static string GetKey(string key) { return ms_prefix + "_" + key; } } } ================================================ FILE: SGFUnity/Common/DelayInvoker.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * DelayInvoker * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using System.Collections; namespace SGF.Unity.Common { public delegate void DelayFunction(object[] args); public class DelayInvoker : MonoSingleton { private List m_lstHelper; private List m_lstUnscaledHelper; private static WaitForEndOfFrame ms_waitForEndOfFrame = new WaitForEndOfFrame(); class DelayHelper { public object group; public float delay; public DelayFunction func; public object[] args; public void Invoke() { if (func != null) { try { func(args); } catch(Exception e) { Debuger.LogError("DelayInvoker", "Invoke() Error:{0}\n{1}", e.Message, e.StackTrace); } } } } public static void DelayInvoke(object group, float delay, DelayFunction func, params object[] args) { DelayInvoker.Instance.DelayInvokeWorker(group, delay, func, args); } public static void DelayInvoke(float delay, DelayFunction func, params object[] args) { DelayInvoker.Instance.DelayInvokeWorker(null, delay, func, args); } public static void UnscaledDelayInvoke(float delay, DelayFunction func, params object[] args) { DelayInvoker.Instance.UnscaledDelayInvokeWorker(null, delay, func, args); } public static void CancelInvoke(object group) { DelayInvoker.Instance.CancelInvokeWorker(group); } //==================================================================== private void DelayInvokeWorker(object group, float delay, DelayFunction func, params object[] args) { if (m_lstHelper == null) { m_lstHelper = new List(); } DelayHelper helper = new DelayHelper(); helper.group = group; helper.delay = delay; helper.func += func; helper.args = args; m_lstHelper.Add(helper); } private void UnscaledDelayInvokeWorker(object group, float delay, DelayFunction func, params object[] args) { if (m_lstUnscaledHelper == null) { m_lstUnscaledHelper = new List(); } DelayHelper helper = new DelayHelper(); helper.group = group; helper.delay = delay; helper.func += func; helper.args = args; m_lstUnscaledHelper.Add(helper); } private void CancelInvokeWorker(object group) { if (null != m_lstHelper) { if (group == null) { for (int i = 0; i < m_lstHelper.Count; i++) { m_lstHelper[i] = null; } m_lstHelper.Clear(); return; } for (int i = 0; i < m_lstHelper.Count(); ++i) { DelayHelper helper = m_lstHelper[i]; if (helper.group == group) { m_lstHelper.RemoveAt(i); i--; } } } } //==================================================================== void Update() { if (null != m_lstHelper) { for (int i = 0; i < m_lstHelper.Count(); ++i) { DelayHelper helper = m_lstHelper[i]; helper.delay -= UnityEngine.Time.deltaTime; if (helper.delay <= 0) { m_lstHelper.RemoveAt(i); i--; helper.Invoke(); } } } if (null != m_lstUnscaledHelper) { for (int i = 0; i < m_lstUnscaledHelper.Count(); ++i) { DelayHelper helper = m_lstUnscaledHelper[i]; helper.delay -= UnityEngine.Time.unscaledDeltaTime; if (helper.delay <= 0) { m_lstUnscaledHelper.RemoveAt(i); i--; helper.Invoke(); } } } } void OnDisable() { // Debug.Log("DelayInvoker Release!!!"); CancelInvoke(null); this.StopAllCoroutines(); } //==================================================================== public static void DelayInvokerOnEndOfFrame(DelayFunction func, params object[] args) { Instance.StartCoroutine(DelayInvokerOnEndOfFrameWorker(func, args)); } private static IEnumerator DelayInvokerOnEndOfFrameWorker(DelayFunction func, params object[] args) { yield return ms_waitForEndOfFrame; //Profiler.BeginSample("DelayInvoker_DelayInvokerOnEndOfFrame"); try { func(args); } catch (Exception e) { Debuger.LogError("DelayInvoker", "DelayInvokerOnEndOfFrame() Error:{0}\n{1}", e.Message, e.StackTrace); } //Profiler.EndSample(); } public static void FixedTimeInvoke(int hours, int minitue) { } } } ================================================ FILE: SGFUnity/Common/MonoHelper.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * MonoHelper * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections; using UnityEngine; namespace SGF.Unity.Common { public delegate void MonoUpdaterEvent(); public class MonoHelper : MonoSingleton { //=========================================================== private event MonoUpdaterEvent UpdateEvent; private event MonoUpdaterEvent FixedUpdateEvent; public static void AddUpdateListener(MonoUpdaterEvent listener) { if (Instance != null) { Instance.UpdateEvent += listener; } } public static void RemoveUpdateListener(MonoUpdaterEvent listener) { if (Instance != null) { Instance.UpdateEvent -= listener; } } public static void AddFixedUpdateListener(MonoUpdaterEvent listener) { if (Instance != null) { Instance.FixedUpdateEvent += listener; } } public static void RemoveFixedUpdateListener(MonoUpdaterEvent listener) { if (Instance != null) { Instance.FixedUpdateEvent -= listener; } } void Update() { if (UpdateEvent != null) { try { UpdateEvent(); } catch (Exception e) { Debuger.LogError("MonoHelper", "Update() Error:{0}\n{1}", e.Message, e.StackTrace); } } } void FixedUpdate() { if (FixedUpdateEvent != null) { try { FixedUpdateEvent(); } catch (Exception e) { Debuger.LogError("MonoHelper", "FixedUpdate() Error:{0}\n{1}", e.Message, e.StackTrace); } } } //=========================================================== public new static void StartCoroutine(IEnumerator routine) { MonoBehaviour mono = Instance; mono.StartCoroutine(routine); } } } ================================================ FILE: SGFUnity/Common/MonoSingleton.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Mono单例 * MonoSingleton * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using UnityEngine; namespace SGF.Unity.Common { public abstract class MonoSingleton : MonoBehaviour where T : MonoSingleton { private static T ms_instance; public static T Instance { get { if (ms_instance == null) { ms_instance = Instantiate(); } return ms_instance; } } protected static T Instantiate() { if (ms_instance == null) { ms_instance = (T)FindObjectOfType(typeof(T)); if (FindObjectsOfType(typeof(T)).Length > 1) { return ms_instance; } if (ms_instance == null) { GameObject singleton = new GameObject("[Singleton]" + typeof(T).Name); if (singleton != null) { ms_instance = singleton.AddComponent(); ms_instance.InitSingleton(); } } } return ms_instance; } protected virtual void InitSingleton() { } private void Awake() { if (ms_instance == null) { ms_instance = this as T; } } public void OnApplicationQuit() { ms_instance = null; } } } ================================================ FILE: SGFUnity/DebugerGUI/NetDebugerGUI.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * DebugerGUI * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.IO; using SGF.Network; using SGF.Network.protocol; using SGF.Unity.UI.SGUI; using SGF.Utils; using UnityEngine; namespace SGF.Unity.DebugerGUI { public class NetDebugerGUI { public const string TAG = "NetDebugerGUI"; private static bool m_UseRealtimeProfile = false; private static string m_dbgFileName = ""; public static void Init() { NetDebuger.EnableLog = NetDebuger.EnableLog; SGFDebugerGUI.AddDbgGUI("NetDebuger", OnDbgGUI); } private static void OnDbgGUI() { NetDebuger.EnableLog = GUILayout.Toggle(NetDebuger.EnableLog, "NetDebuger.EnableLog"); GUILayout.BeginHorizontal(); { GUILayout.BeginVertical(); { NetDebuger.EnableProfiler = GUILayout.Toggle(NetDebuger.EnableProfiler, "NetDebuger.EnableProfiler"); if (NetDebuger.EnableProfiler) { OnDbgGUI_ProfilerControl(); } } GUILayout.EndVertical(); GUILayout.BeginVertical(); { NetDebuger.EnableWeakNet = GUILayout.Toggle(NetDebuger.EnableWeakNet, "NetDebuger.EnableWeakNet"); if (NetDebuger.EnableWeakNet) { OnDbgGUI_WeakNetControl(); } } GUILayout.EndVertical(); } GUILayout.EndHorizontal(); GUILayout.Space(5); GUILayout.Box("", GUILayout.Height(1)); GUILayout.BeginHorizontal(); { if (m_UseRealtimeProfile) { Color old = GUI.color; GUI.color = Color.red; GUILayout.Button("Realtime Profiler"); GUI.color = old; if (GUILayout.Button("Offline Profiler")) { m_UseRealtimeProfile = false; } } else { if (GUILayout.Button("Realtime Profiler")) { m_UseRealtimeProfile = true; } Color old = GUI.color; GUI.color = Color.red; GUILayout.Button("Offline Profiler"); GUI.color = old; } } GUILayout.EndHorizontal(); if (m_UseRealtimeProfile) { OnDbgGUI_RealtimeProfiler(); } else { OnDbgGUI_OfflineProfiler(); } } private static void OnDbgGUI_ProfilerControl() { if (GUILayout.Button("Clear Profiler Cache")) { NetDebuger.ClearSample(); m_dbgFileName = null; } if (string.IsNullOrEmpty(m_dbgFileName)) { m_dbgFileName = GetDefaultFileName(); } GUILayout.Label("Input Profiler FileName:"); m_dbgFileName = GUILayout.TextField(m_dbgFileName); if (GUILayout.Button("Save Profiler File")) { NetDebugFile file = new NetDebugFile(); file.Content.profiler_samples.AddRange(NetDebuger.SampleList); file.Save(NetDebuger.DbgFileDir, m_dbgFileName); NetDebuger.ClearSample(); m_dbgFileName = null; CheckFileList(); } } private static void OnDbgGUI_WeakNetControl() { GUILayout.Label("Packet Loss Rate: " + (int)(NetDebuger.PacketLossRate * 100) + "%"); NetDebuger.PacketLossRate = GUILayout.HorizontalSlider(NetDebuger.PacketLossRate, 0, 1f); GUILayout.Label("Jitter Rate: " + (int)(NetDebuger.JitterRate * 100) + "%"); NetDebuger.JitterRate = GUILayout.HorizontalSlider(NetDebuger.JitterRate, 0, 1f); GUILayout.Label(string.Format("Jitter Delay: [{0} ~ {1}] ms", NetDebuger.JitterDelayMin, NetDebuger.JitterDelayMax)); GUILayout.BeginHorizontal(); { GUILayout.Label("Min:", GUILayout.Width(50)); NetDebuger.JitterDelayMin = (int)GUILayout.HorizontalSlider(NetDebuger.JitterDelayMin, 0, 200); if (NetDebuger.JitterDelayMin > NetDebuger.JitterDelayMax) { NetDebuger.JitterDelayMin = NetDebuger.JitterDelayMax; } } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); { GUILayout.Label("Max:", GUILayout.Width(50)); NetDebuger.JitterDelayMax = (int)GUILayout.HorizontalSlider(NetDebuger.JitterDelayMax, 0, 2000); if (NetDebuger.JitterDelayMax < NetDebuger.JitterDelayMin) { NetDebuger.JitterDelayMax = NetDebuger.JitterDelayMin; } } GUILayout.EndHorizontal(); } //======================================================================== //Realtime Profiler private static DictionarySafe m_mapProfileCurve; private static DictionarySafe> m_mapProfileSampleList; private bool m_RealTimeUpdate = true; private static int m_NumPerPage = 50; private int m_MaxTimePerLog = 500;//MS private int m_TotalCnt = 0; private static int m_profileNextIndex = 0; private static void OnDbgGUI_RealtimeProfiler() { if (m_mapProfileCurve == null) { m_mapProfileCurve = new DictionarySafe(); } if (m_mapProfileSampleList == null) { m_mapProfileSampleList = new DictionarySafe>(); } try { UpdateProfileSampleList(); } catch (Exception e) { Debuger.LogError(TAG, "OnDbgGUI_RealtimeProfiler() UpdateProfileSampleList: " + e.Message); } GUILayout.Label("每屏数据采样个数:" + m_NumPerPage); m_NumPerPage = (int)GUILayout.HorizontalSlider(m_NumPerPage, 10, 1800); foreach (KeyValuePair> pair in m_mapProfileSampleList) { string name = pair.Key; GUICurve curve = m_mapProfileCurve[name]; bool toggle = (bool) curve.state; toggle = GUILayout.Toggle(toggle, name); curve.state = toggle; if (toggle) { OnGUI_ReportProfiler(curve,pair.Value); } } } private static void UpdateProfileSampleList() { List list = NetDebuger.SampleList; int totalCnt = list.Count; if (m_profileNextIndex > totalCnt) { m_mapProfileSampleList = new DictionarySafe>(); m_mapProfileCurve = new DictionarySafe(); m_profileNextIndex = 0; } while (m_profileNextIndex < totalCnt) { NetSampleItem item = list[m_profileNextIndex]; List listTemp = m_mapProfileSampleList[item.name]; if (listTemp == null) { listTemp = new List(); m_mapProfileSampleList.Add(item.name, listTemp); GUICurve curve = new GUICurve(); curve.state = false; m_mapProfileCurve.Add(item.name, curve); } listTemp.Add(item); m_profileNextIndex++; } } private static float m_profilerRangeMinY = 0; private static float m_profilerRangeMaxY = 200; private static void OnGUI_ReportProfiler(GUICurve curve, List list) { curve.Clear(); if (list != null) { int beginIndex = list.Count - (int)m_NumPerPage; if (beginIndex < 0) { beginIndex = 0; } List listPoints = NetDebugerGUI.DoAnalyseBasic(list, beginIndex); for (int i = 0; i < listPoints.Count; i++) { curve.AddPoint(listPoints[i]); } } float minY = m_profilerRangeMinY; float maxY = m_profilerRangeMaxY; GUILayout.Label("RangeY:"); GUILayout.BeginHorizontal(); minY = GUILayout.HorizontalSlider(minY, 0, maxY); maxY = GUILayout.HorizontalSlider(maxY, minY, 200); GUILayout.EndHorizontal(); curve.SetRangeY(minY, maxY); m_profilerRangeMinY = minY; m_profilerRangeMaxY = maxY; curve.DrawLayout(GUILayout.Height(200)); Rect rect = GUILayoutUtility.GetLastRect(); GUI.Label(rect, string.Format("X:[ {0} , {1} ]\nY:[ {2} , {3} ]", curve.MinX, curve.MaxX, curve.MinY, curve.MaxY)); } //======================================================================== //Offline Profiler #region Offline Profiler private static List m_listDbgFileName; private static DictionarySafe m_mapDbgFileToggle; private static DictionarySafe m_mapDbgFile; private static DictionarySafe m_mapCurve; private static void OnDbgGUI_OfflineProfiler() { if (GUILayout.Button("Refresh Profiler File List")) { CheckFileList(); } GUILayout.Label("File List:"); if (m_listDbgFileName != null) { for (int i = 0; i < m_listDbgFileName.Count; i++) { string filename = m_listDbgFileName[i]; bool toggle = m_mapDbgFileToggle[filename]; toggle = GUILayout.Toggle(toggle, filename); m_mapDbgFileToggle[filename] = toggle; if (toggle) { OnDbgGUI_AnalyseFile(filename); } GUILayout.Box("", GUILayout.Height(2)); } } } private static void OnDbgGUI_AnalyseFile(string filename) { NetDebugFile file = m_mapDbgFile[filename]; if (file == null) { file = new NetDebugFile(); file.Open(NetDebuger.DbgFileDir, filename); m_mapDbgFile.Add(filename,file); } for (int i = 0; i < file.ListAllSampleName.Count; i++) { string name = file.ListAllSampleName[i]; GUICurve curve = m_mapCurve[filename + ">" + name]; if (curve == null) { curve = new GUICurve(); curve.state = false; m_mapCurve[filename + ">" + name] = curve; } bool toggle = (bool)curve.state; toggle = GUILayout.Toggle(toggle, name); curve.state = toggle; if (toggle) { OnDbgGUI_ReportFileCurve(curve, file, name); } } } private static void OnDbgGUI_ReportFileCurve(GUICurve curve, NetDebugFile file, string sampleName) { if (curve.Length == 0) { List list = file.GetSampleList(sampleName); List listPoints = DoAnalyseBasic(list); curve.AddRangePoint(listPoints); } float minY = curve.MinY; float maxY = curve.MaxY; GUILayout.Label("RangeY:"); GUILayout.BeginHorizontal(); minY = GUILayout.HorizontalSlider(minY, 0, maxY); maxY = GUILayout.HorizontalSlider(maxY, minY, 200); GUILayout.EndHorizontal(); curve.SetRangeY(minY, maxY); curve.DrawLayout(GUILayout.Height(200)); Rect rect = GUILayoutUtility.GetLastRect(); GUI.Label(rect, string.Format("X:[ {0} , {1} ]\nY:[ {2} , {3} ]", curve.MinX, curve.MaxX, curve.MinY, curve.MaxY)); } #endregion //======================================================================== //数据处理 public static List DoAnalyseBasic(List list, int beginIndex = 0, int endIndex = 0) { if (list == null || list.Count < 2) { return null; } if (beginIndex < 0 || beginIndex >= list.Count) { beginIndex = 0; } if (endIndex <= 0 || endIndex > list.Count) { endIndex = list.Count; } if (endIndex - beginIndex < 2) { return null; } List listPoint = new List(); for (int i = beginIndex; i < endIndex; i++) { if (list[i] == null) { break; } long dtime = 0; if (i > 0) { dtime = list[i].time - list[i - 1].time; } else if (list.Count > 1) { dtime = list[i + 1].time - list[i].time; } Vector2 v = new Vector2(); v.x = i; v.y = dtime / 10000.0f; if (v.y > 200) { v.y = 200; } listPoint.Add(v); } return listPoint; } //============================================================= // #region 工具函数 public static string GetDefaultFileName() { string filename; DateTime now = DateTime.Now; filename = "FSPDebuger_" + now.GetDateTimeFormats('s')[0].ToString(); //2005-11-05T14:06:25 filename = filename.Replace("-", "_"); filename = filename.Replace(":", "_"); filename = filename.Replace(" ", ""); filename += ".fsp"; return filename; } private static void CheckFileList() { m_listDbgFileName = new List(); m_mapDbgFileToggle = new DictionarySafe(); m_mapDbgFile = new DictionarySafe(); m_mapCurve = new DictionarySafe(); try { DirectoryInfo dirinfo = new DirectoryInfo(NetDebuger.DbgFileDir); if (dirinfo.Exists == false) { return; } FileInfo[] files = dirinfo.GetFiles("*", SearchOption.TopDirectoryOnly); for (int i = 0; i < files.Length; i++) { m_listDbgFileName.Add(files[i].Name); } } catch (IOException e) { Debuger.LogWarning(TAG, "CheckFileList() Error:" + e.Message); } } #endregion } } ================================================ FILE: SGFUnity/DebugerGUI/SGFDebugerGUI.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * SGFDebugerGUI * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Text; using SGF.Unity.Common; using SGF.Utils; using UnityEngine; using UnityEngine.UI; namespace SGF.Unity.DebugerGUI { public class SGFDebugerGUI : SGFDebugerGUIBase { public const string BasePath = "Assets/SGF/Debuger/"; public const string UIBasePath = "Assets/Resources/"; public const string Permission_Log = "Log"; #region 一个完整的SGFDebugerGUI类 private static SGFDebugerGUI ms_Instance; public new static void Show(string permission) { if (string.IsNullOrEmpty(permission)) { return; } if (ms_Instance == null) { GameObject prefab = (GameObject)Resources.Load("SGFDebugerGUI"); if (prefab != null) { GameObject obj = (GameObject) Instantiate(prefab); ms_Instance = obj.GetComponent(); DontDestroyOnLoad(obj); } } if(ms_Instance!=null) { ms_Instance.EnsureLogCallback(); (ms_Instance as SGFDebugerGUIBase).Show(permission); } } public static void Show(string openId, string permission) { //采用OpenId作为权限检查对象 if (string.IsNullOrEmpty(openId)) { return; } permission = ValidPermissionInWhiteList(permission, openId); if (string.IsNullOrEmpty(permission)) { return; } Show(permission); } public new static void Hide() { if (ms_Instance != null) { (ms_Instance as SGFDebugerGUIBase).Hide(); //Destroy(ms_Instance.gameObject); //ms_Instance = null; } } #endregion #region 白名单控制 private static readonly string[] WhiteList_Admin = { //Slicol "5FEF17CFD26A88F5C9349B71D3AD1DBE", "C4FD8FAE90332C1EEF96443415127AC4", "2383818E509286DDEF99183DB3E251D7", "2A02EC0596D89486937A411680F9071E", "ozwwNjxOTUPKIqEZk-hQ9pEkeTsA", "ozwwNj3hYrjqN9mx7Yskg3UoGj1U", }; private static readonly string[] WhiteList_Log = { }; private static DictionarySafe MapWhiteList; private static string ValidPermissionInWhiteList(string permission, string openId) { if (MapWhiteList == null) { MapWhiteList = new DictionarySafe(); MapWhiteList.Add(Permission_Admin, WhiteList_Admin); MapWhiteList.Add(Permission_Log, WhiteList_Log); //TODO 新的白名单在这里增加 } if (string.IsNullOrEmpty(permission)) { bool valided = (Array.IndexOf(WhiteList_Admin, openId) >= 0); if (valided) { return Permission_Admin; } permission = ""; foreach (KeyValuePair pair in MapWhiteList) { valided = (Array.IndexOf(pair.Value, openId) >= 0); if (valided) { if (permission == "") { permission = pair.Key; } else { permission = permission + "|" + pair.Key; } } } } else { bool valided = false; if (MapWhiteList.ContainsKey(permission)) { valided = (Array.IndexOf(MapWhiteList[permission], openId) >= 0); } if (!valided) { permission = ""; } } return permission; } #endregion //========================================================================================= private GUIStyle m_lowerLeftFontStyle; //========================================================================================= public Image UIMask; //========================================================================================= override protected void Awake() { base.Awake(); ms_Instance = this; m_lowerLeftFontStyle = new GUIStyle(); m_lowerLeftFontStyle.clipping = TextClipping.Clip; m_lowerLeftFontStyle.border = new RectOffset(0, 0, 0, 0); m_lowerLeftFontStyle.normal.background = null; m_lowerLeftFontStyle.fontSize = 12; m_lowerLeftFontStyle.normal.textColor = Color.white; m_lowerLeftFontStyle.fontStyle = FontStyle.Bold; m_lowerLeftFontStyle.alignment = TextAnchor.LowerLeft; if (UIMask != null) { UIMask.gameObject.SetActive(true); } } protected void Start() { AddDbgGUI("日志", OnGUI_LogToggle, Permission_Log); } public void EnsureLogCallback() { } override protected void OnTitleGUI(Rect rect) { } protected override void OnCustomGUI(Rect rect) { } protected override void OnMaskGUI(Rect rect) { if (UIMask != null) { UIMask.rectTransform.sizeDelta = new Vector2(rect.width, rect.height); UIMask.rectTransform.localPosition = new Vector3(rect.x - Screen.width/2 + rect.width/2, Screen.height/2 - rect.y - rect.height/2); } } private Vector2 GUI2ScreenPoint(Vector2 v) { return new Vector2(v.x, Screen.height - v.y); } private Vector2 ScreenToGUIPoint(Vector2 v) { return new Vector2(v.x, Screen.height - v.y); } //========================================================================================== // private static string m_LogUploadTips = ""; private static string m_LogUploadUrl = "http://101.227.153.40:8080/replay"; private static bool m_IsLogUploading = false; private static string m_LogReportText = ""; private void OnGUI_LogToggle() { GUILayout.BeginVertical(); Debuger.EnableLog = GUILayout.Toggle(Debuger.EnableLog, "Debuger.EnableLog"); Debuger.EnableTime = GUILayout.Toggle(Debuger.EnableTime, "Debuger.EnableTime"); Debuger.EnableStack = GUILayout.Toggle(Debuger.EnableStack, "Debuger.EnableStack"); Debuger.EnableSave = GUILayout.Toggle(Debuger.EnableSave, "Debuger.EnableSave"); if (Debuger.EnableSave) { GUILayout.TextArea(Debuger.LogFileDir); GUILayout.TextField(Debuger.LogFileName); if (!string.IsNullOrEmpty(m_LogUploadTips)) { GUILayout.Label("Upload Tips:" + m_LogUploadTips); } if (GUILayout.Button("上传日志")) { UploadLog(); } } GUILayout.Space(5); if (!string.IsNullOrEmpty(m_LogReportText)) { GUILayout.Label("当前日志"); GUILayout.Label(m_LogReportText); } if (GUILayout.Button("显示或者刷新日志")) { byte[] logBytes = LoadCurrentLogFile(); if (logBytes != null && logBytes.Length > 0) { string logStr = Encoding.UTF8.GetString(logBytes); if (logStr.Length >= 15000) { m_LogReportText = logStr.Substring(logStr.Length - 15000); } else if (m_LogReportText.Length + logStr.Length >= 15000) { m_LogReportText = m_LogReportText.Substring(m_LogReportText.Length - (15000 - logStr.Length)); m_LogReportText += logStr; } else { m_LogReportText += logStr; } } } GUILayout.EndVertical(); } //========================================================================================== #region 读取日志文本 private static byte[] LoadCurrentLogFile() { string fullpath = Debuger.LogFileDir + Debuger.LogFileName; if (!File.Exists(fullpath)) { Debuger.LogError("SGFDebugerGUI", "LoadCurrentLogFile() File Is Not Exist:" + fullpath); return null; } try { if (Debuger.LogFileWriter != null) { Debuger.LogFileWriter.Close(); Debuger.LogFileWriter = null; Debuger.LogWarning("SGFDebugerGUI", "LoadCurrentLogFile() 取出当前日志文件内容,之后的日志将存入新的日志文件!"); } byte[] bytes = FileUtils.ReadFile(fullpath); return bytes; } catch (Exception e) { Debuger.LogError("SGFDebugerGUI", "LoadCurrentLogFile() Failed: " + e.Message + e.StackTrace); return null; } } #endregion //========================================================================================== #region 上传日志 public static void UploadLog() { if (m_IsLogUploading) { m_LogUploadTips = "正在上传中,请稍候再操作.."; return; } try { byte[] bytes = LoadCurrentLogFile(); if (bytes != null && bytes.Length > 0) { WWWForm form = new WWWForm(); form.AddField("User", 0); form.AddField("Time", (int)TimeUtils.GetTotalSecondsSince1970()); form.AddBinaryData("Content", bytes); WWW www = new WWW(m_LogUploadUrl, form); MonoHelper.StartCoroutine(UploadLogPost(www)); m_IsLogUploading = true; } } catch (Exception e) { Debuger.LogError("SGFDebugerGUI", "Upload() Failed: " + e.Message + e.StackTrace); return; } } private static IEnumerator UploadLogPost(WWW www) { m_LogUploadTips = "开始上传..."; yield return www; m_IsLogUploading = false; if (www.error != null) { m_LogUploadTips = "上传失败!"; Debuger.LogError("SGFDebugerGUI", "Upload() Failed: " + www.error); } else { m_LogUploadTips = "上传完成!"; Debuger.Log("SGFDebugerGUI", "Upload() Complete!!!"); } } #endregion } } ================================================ FILE: SGFUnity/DebugerGUI/SGFDebugerGUIBase.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * SGFDebugerGUIBase * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Diagnostics; using UnityEngine; namespace SGF.Unity.DebugerGUI { public class SGFDebugerGUIBase : MonoBehaviour { public const string Permission_Admin = "Admin"; private const string PrefsKey_SelectedGUI = "SGFDebugerGUI_SelectedGUI"; class DbgGUIProxy { public string name; public string permission; public Action handler; } public static bool FullScreen = true; public static bool UseBigGUI = true; public static bool EnableSelectedFirst = true; //DbgCmd系统 #region DbgCmd系统 private static Dictionary ms_MapDbgGUI = new Dictionary(); private static List ms_ListDbgGUI = new List(); private static string ms_SelectedGUI = null; /// /// 注册一个DbgGUI /// /// /// /// 默认是需要管理员权限的 public static void AddDbgGUI(string name, Action handler, string permission = Permission_Admin) { if (ms_MapDbgGUI.ContainsKey(name)) { DbgGUIProxy proxy = ms_MapDbgGUI[name]; proxy.handler = handler; proxy.permission = permission; } else { DbgGUIProxy proxy = new DbgGUIProxy(); proxy.name = name; proxy.permission = permission; proxy.handler = handler; ms_MapDbgGUI.Add(name, proxy); if (name == ms_SelectedGUI && EnableSelectedFirst) { ms_ListDbgGUI.Insert(0,proxy); } else { ms_ListDbgGUI.Add(proxy); } } } public static void RemoveDbgGUI(string name) { if (ms_MapDbgGUI.ContainsKey(name)) { if (ms_SelectedGUI == name) { ms_SelectedGUI = null; } DbgGUIProxy proxy = ms_MapDbgGUI[name]; ms_ListDbgGUI.Remove(proxy); ms_MapDbgGUI.Remove(name); } } #endregion //========================================================================================= #region SGFDebugerGUI的View实现 private GUIStyle m_WinStyle; public int BaseSizeBig = 80; public int BaseSizeSmall = 40; private int m_BaseSize = 40; public int BaseSize { get { return m_BaseSize; } } public GUISkin GUISkinBig; public GUISkin GUISkinSmall; private GUISkin m_GuiSkin; //========================================================================================= //========================================================================================= public Rect WinRect; public Rect WinRectMin = new Rect(0, 0, 150, 100); public Rect WinRectMaxSmall = new Rect(0, 0, 500, 600); public Rect WinRectMaxBig = new Rect(0, 0, 1000, 1200); private bool m_IsExpended = false; public bool IsExpended { get { return m_IsExpended; } } private bool m_IsVisible = false; private string m_Permission = ""; //========================================================================================= public static string StatusBarInfo = ""; private int m_StatusBarHeight = 40; //========================================================================================= protected virtual void Awake() { UpdateGUISkin(); DontDestroyOnLoad(this.gameObject); WinRect = WinRectMin; //ms_SelectedGUI = PlayerPrefs.GetString(PrefsKey_SelectedGUI, null); } private void UpdateGUISkin() { if (UseBigGUI) { m_BaseSize = BaseSizeBig; m_GuiSkin = GUISkinBig; } else { m_BaseSize = BaseSizeSmall; m_GuiSkin = GUISkinSmall; } WinRectMin = new Rect(0, 0, (m_BaseSize + 4) * 2, m_BaseSize+4); } //========================================================================================= internal void Show(string permission) { if (m_Permission != Permission_Admin) { string[] tmp = permission.Split('|'); for (int i = 0; i < tmp.Length; i++) { if (m_Permission.IndexOf(tmp[i]) < 0) { m_Permission = m_Permission + "|" + tmp[i]; } } } m_IsVisible = true; ms_SelectedGUI = PlayerPrefs.GetString(PrefsKey_SelectedGUI, null); } internal void Hide() { m_IsVisible = false; } //========================================================================================= private void OnGUI() { if (!m_IsVisible) { return; } if (m_WinStyle == null) { m_WinStyle = new GUIStyle(GUI.skin.window); m_WinStyle.normal.textColor = Color.white; m_WinStyle.alignment = TextAnchor.MiddleCenter; } GUI.color = Color.white; WinRect = GUI.Window(0, WinRect, OnWindow, "", m_WinStyle); OnMaskGUI(WinRect); OnCustomGUI(WinRect); OnStatusGUI(); } private void OnWindow(int windowID) { getDownPos(); GUI.skin.button.fixedHeight = m_BaseSize; if (!m_IsExpended) { if (GUI.Button(new Rect(2, 2, m_BaseSize, m_BaseSize), "∨")) { m_IsExpended = true; } GUI.DragWindow(new Rect(0, 0, Screen.width, Screen.height)); return; } GUI.Box(new Rect(2, 2, WinRect.width - 4, m_BaseSize), ""); Rect rect = new Rect(2, 2, m_BaseSize, m_BaseSize); if (GUI.Button(rect, "∧")) { WinRect.width = WinRectMin.width; WinRect.height = WinRectMin.height; m_IsExpended = false; return; } rect.x += m_BaseSize + 2; if (GUI.Button(rect, UseBigGUI ? "小" : "大")) { UseBigGUI = !UseBigGUI; UpdateGUISkin(); } rect.x += m_BaseSize + 2; rect.width = (int)(m_BaseSize*1.2); if (GUI.Button(rect, FullScreen ? "全屏√" : "全屏 ")) { FullScreen = !FullScreen; } rect.x += m_BaseSize + 2; rect.width = WinRect.width - 2 - rect.x; OnTitleGUI(rect); GUI.skin = m_GuiSkin; OnGUI_DbgCmdSystem(); if (FullScreen) { WinRect.x = 0; WinRect.y = 0; WinRect.width = Screen.width; WinRect.height = Screen.height - m_StatusBarHeight; } else { if (UseBigGUI) { WinRect.width = WinRectMaxBig.width; WinRect.height = System.Math.Min(WinRectMaxBig.height, Screen.height); } else { WinRect.width = WinRectMaxSmall.width; WinRect.height = System.Math.Min(WinRectMaxSmall.height, Screen.height); } //Debug.Log(m_winRect.y + " ... " + downPos.y); if ((Screen.height - downPos.y) - WinRect.y < m_BaseSize + 4) { GUI.DragWindow(new Rect(0, 0, Screen.width, Screen.height)); } } } protected virtual void OnCustomGUI(Rect rect) { } protected virtual void OnMaskGUI(Rect rect) { } protected virtual void OnTitleGUI(Rect rect) { } private void OnStatusGUI() { if (!string.IsNullOrEmpty(StatusBarInfo)) { GUI.Label(new Rect(0, Screen.height - m_StatusBarHeight, Screen.width, m_StatusBarHeight), StatusBarInfo); } } //========================================================================================= //Win绘制 private Vector2 m_ScrollPosition_CmdList = new Vector2(); private Vector2 m_ScrollPosition_CmdGUI = new Vector2(); private float m_OldDrag_CmdGUI; private float m_OldDrag_CmdList; private void OnGUI_DbgCmdSystem() { getDownPos(); //命令列表 OnGUI_CmdList(); //命令内容 OnGUI_CmdGUI(); } private void OnGUI_CmdList() { Rect rtCmdList = new Rect(); rtCmdList.x += 2; rtCmdList.y += (m_BaseSize + 4); rtCmdList.width = m_BaseSize*3 + 10; rtCmdList.height = WinRect.height - (m_BaseSize + 4) - 2; GUILayout.BeginArea(rtCmdList); { Vector2 drag = getDrag(); if (drag.y != 0 && rtCmdList.Contains(new Vector2(downPos.x - WinRect.x, Screen.height - downPos.y - WinRect.y))) { m_ScrollPosition_CmdList.y += (drag.y - m_OldDrag_CmdList); } m_ScrollPosition_CmdList = GUILayout.BeginScrollView(m_ScrollPosition_CmdList); { m_OldDrag_CmdList = drag.y; GUILayout.BeginVertical(); { bool isSelectChanged = false; DbgGUIProxy newSelectProxy = null; for (int i = 0; i < ms_ListDbgGUI.Count; i++) { DbgGUIProxy proxy = ms_ListDbgGUI[i]; if (m_Permission.IndexOf(Permission_Admin) >= 0 || m_Permission.IndexOf(proxy.permission) >= 0) { if (ms_SelectedGUI != proxy.name) { if (GUILayout.Button(proxy.name, GUILayout.Width(m_BaseSize * 3 - 5), GUILayout.Height(m_BaseSize))) { ms_SelectedGUI = proxy.name; isSelectChanged = true; newSelectProxy = proxy; } } else { GUI.skin.box.alignment = TextAnchor.MiddleCenter; Color oldColor = GUI.color; GUI.color = Color.red; GUILayout.Box(proxy.name, GUILayout.Width(m_BaseSize * 3 - 5), GUILayout.Height(m_BaseSize)); GUI.color = oldColor; } } } if (isSelectChanged) { PlayerPrefs.SetString(PrefsKey_SelectedGUI, ms_SelectedGUI); if (EnableSelectedFirst) { ms_ListDbgGUI.Remove(newSelectProxy); ms_ListDbgGUI.Insert(0, newSelectProxy); } } } GUILayout.EndVertical(); } GUILayout.EndScrollView(); } GUILayout.EndArea(); } private void OnGUI_CmdGUI() { Rect rtCmdGUI = new Rect(); rtCmdGUI.x += m_BaseSize * 3 + 2; rtCmdGUI.y += (m_BaseSize + 4); rtCmdGUI.width = WinRect.width - (m_BaseSize * 3 + 2) - 2; rtCmdGUI.height = WinRect.height - (m_BaseSize + 4) - 2; GUILayout.BeginArea(rtCmdGUI); { Vector2 drag = getDrag(); if (drag.y != 0 && rtCmdGUI.Contains(new Vector2(downPos.x - WinRect.x, Screen.height - downPos.y - WinRect.y))) { m_ScrollPosition_CmdGUI.y += (drag.y - m_OldDrag_CmdGUI); } m_ScrollPosition_CmdGUI = GUILayout.BeginScrollView(m_ScrollPosition_CmdGUI); { m_OldDrag_CmdGUI = drag.y; if (ms_MapDbgGUI != null && ms_SelectedGUI != null) { if (ms_MapDbgGUI.ContainsKey(ms_SelectedGUI)) { GUI.skin.button.fixedHeight = m_BaseSize; GUI.skin.toggle.fixedHeight = m_BaseSize/2; DbgGUIProxy proxy = ms_MapDbgGUI[ms_SelectedGUI]; Action handler = proxy.handler; handler(); } } } GUILayout.EndScrollView(); } GUILayout.EndArea(); } #region Drag相关 Vector2 mousePosition; Vector2 getDrag() { if (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer) { if (Input.touches.Length != 1) { return Vector2.zero; } return Input.touches[0].position - downPos; } else { if (Input.GetMouseButton(0)) { mousePosition = Input.mousePosition; return mousePosition - downPos; } else { return Vector2.zero; } } } Vector2 startPos; Vector2 downPos; Vector2 getDownPos() { if (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer) { if (Input.touches.Length == 1 && Input.touches[0].phase == TouchPhase.Began) { downPos = Input.touches[0].position; return downPos; } } else { if (Input.GetMouseButtonDown(0)) { downPos.x = Input.mousePosition.x; downPos.y = Input.mousePosition.y; return downPos; } } return Vector2.zero; } #endregion //========================================================================================== // #endregion } } ================================================ FILE: SGFUnity/Extension/BitmapDrawingExtensions.cs ================================================ using System; using UnityEngine; using System.Collections.Generic; /** The MIT License (MIT) Copyright (c) 2014 Lauri Hosio Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ namespace ProtoTurtle.BitmapDrawing { /// /// A extension class for UnityEngine.Texture2D that provides a bitmap drawing API. /// Provides drawing methods line Line, Circle, Rectangle etc. /// This class uses a convention of having the 0,0 point at the left-top corner! /// /// Check this out for more cool middleware stuff: /// http://prototurtle.com /// /// public static class BitmapDrawingExtensions { public static void Clear(this Texture2D texture) { Rect rect = new Rect(0, 0, texture.width, texture.height); texture.DrawFilledRectangle(rect, Color.clear); } /// /// Draws a pixel just like SetPixel except 0,0 is the left top corner. public static void DrawPixel(this Texture2D texture, int x, int y, Color color) { if (x < 0 || x > texture.width || y < 0 || y > texture.height) { return; } texture.SetPixel(x, TransformToLeftTop_y(y, texture.height), color); } /// /// Draws a pixel just like SetPixel except 0,0 is the left top corner. /// Takes the width and height as parameters - faster for calling this in a loop. /// /// Width of the target bitmap /// Height of the target bitmap public static void DrawPixel(this Texture2D texture, int x, int y, int width, int height, Color color) { if (x < 0 || x > width || y < 0 || y > height) { return; } texture.SetPixel(x, TransformToLeftTop_y(y, height), color); } /// /// Draws a circle with the midpoint being x0, x1. /// Implementation of Bresenham's circle algorithm /// public static void DrawCircle(this Texture2D texture, int x, int y, int radius, Color color) { Circle(texture, x, y, radius, color, false); } /// /// Draws a filled circle with the midpoint being x0, x1. /// Implementation of Bresenham's circle algorithm /// public static void DrawFilledCircle(this Texture2D texture, int x, int y, int radius, Color color) { Circle(texture, x, y, radius, color, true); } private static void Circle(Texture2D texture, int x, int y, int radius, Color color, bool filled = false) { int cx = radius; int cy = 0; int radiusError = 1 - cx; while (cx >= cy) { if (!filled) { PlotCircle(texture, cx, x, cy, y, color); } else { ScanLineCircle(texture, cx, x, cy, y, color); } cy++; if (radiusError < 0) { radiusError += 2 * cy + 1; } else { cx--; radiusError += 2 * (cy - cx + 1); } } } private static void PlotCircle(Texture2D texture, int cx, int x, int cy, int y, Color color) { texture.DrawPixel(cx + x, cy + y, color); // Point in octant 1... texture.DrawPixel(cy + x, cx + y, color); texture.DrawPixel(-cx + x, cy + y, color); texture.DrawPixel(-cy + x, cx + y, color); texture.DrawPixel(-cx + x, -cy + y, color); texture.DrawPixel(-cy + x, -cx + y, color); texture.DrawPixel(cx + x, -cy + y, color); texture.DrawPixel(cy + x, -cx + y, color); // ... point in octant 8 } // Draw scanlines from opposite sides of the circle on y-scanlines instead of just plotting pixels // at the right coordinates private static void ScanLineCircle(Texture2D texture, int cx, int x, int cy, int y, Color color) { //texture.DrawPixel(cx + x, cy + y, color); //texture.DrawPixel(-cx + x, cy + y, color); texture.DrawLine(cx + x, cy + y, -cx + x, cy + y, color); //texture.DrawPixel(cy + x, cx + y, color); //texture.DrawPixel(-cy + x, cx + y, color); texture.DrawLine(cy + x, cx + y, -cy + x, cx + y, color); //texture.DrawPixel(-cx + x, -cy + y, color); //texture.DrawPixel(cx + x, -cy + y, color); texture.DrawLine(-cx + x, -cy + y, cx + x, -cy + y, color); //texture.DrawPixel(-cy + x, -cx + y, color); //texture.DrawPixel(cy + x, -cx + y, color); texture.DrawLine(-cy + x, -cx + y, cy + x, -cx + y, color); } /// /// Starts a flood fill at point startX, startY. /// This is a pretty slow flood fill, biggest bottle neck is comparing two colors which happens /// a lot. Should be a way to make it much faster. /// O(n) space. n = width*height - makes a copy of the bitmap temporarily in the memory /// /// /// /// /// public static void FloodFill(this Texture2D texture, int startX, int startY, Color newColor) { Point start = new Point(startX, TransformToLeftTop_y(startY, texture.height)); Flat2DArray copyBmp = new Flat2DArray(texture.height, texture.width, texture.GetPixels()); Color originalColor = texture.GetPixel(start.X, start.Y); int width = texture.width; int height = texture.height; if (originalColor == newColor) { return; } copyBmp[start.X, start.Y] = newColor; Queue openNodes = new Queue(); openNodes.Enqueue(start); int i = 0; // TODO: remove this // emergency switch so it doesn't hang if something goes wrong int emergency = width * height; while (openNodes.Count > 0) { i++; if (i > emergency) { return; } Point current = openNodes.Dequeue(); int x = current.X; int y = current.Y; if (x > 0) { if (copyBmp[x - 1, y] == originalColor) { copyBmp[x - 1, y] = newColor; openNodes.Enqueue(new Point(x - 1, y)); } } if (x < width - 1) { if (copyBmp[x + 1, y] == originalColor) { copyBmp[x + 1, y] = newColor; openNodes.Enqueue(new Point(x + 1, y)); } } if (y > 0) { if (copyBmp[x, y - 1] == originalColor) { copyBmp[x, y - 1] = newColor; openNodes.Enqueue(new Point(x, y - 1)); } } if (y < height - 1) { if (copyBmp[x, y + 1] == originalColor) { copyBmp[x, y + 1] = newColor; openNodes.Enqueue(new Point(x, y + 1)); } } } texture.SetPixels(copyBmp.data); } // Could be its own file private class Flat2DArray { public Color[] data; private readonly int height; private readonly int width; public Flat2DArray(int height, int width, Color[] data) { this.height = height; this.width = width; this.data = data; } public Color this[int x, int y] { get { return data[x + y * width]; } set { data[x + y * width] = value; } } } private struct Point { public int X; public int Y; public Point(int x, int y) { this.X = x; this.Y = y; } } /// /// Draws a rectangle /// public static void DrawRectangle(this Texture2D texture, Rect rectangle, Color color) { int x = (int)rectangle.x; int y = (int)rectangle.y; int height = (int)rectangle.height; int width = (int)rectangle.width; // top left to bottom left texture.DrawLine(x, y, x, y + height, color); // bottom left to bottom right texture.DrawLine(x, y + height, x + width, y + height, color); // bottom right to top right texture.DrawLine(x + width, y + height, x + width, y, color); // top right to top left texture.DrawLine(x + width, y, x, y, color); } /// /// Fills the given rectangle area with a solid color. public static void DrawFilledRectangle(this Texture2D texture, Rect rectangle, Color color) { Color[] colorsArray = new Color[(int)rectangle.width * (int)rectangle.height]; for (int i = 0; i < colorsArray.Length; i++) { colorsArray[i] = color; } int transformedY = TransformToLeftTop_y(rectangle.y, texture.height) - (int)rectangle.height; texture.SetPixels((int)rectangle.x, transformedY, (int)rectangle.width, (int)rectangle.height, colorsArray); } public static void DrawLine(this Texture2D texture, Vector3 start, Vector3 end, Color color) { Line(texture, (int)start.x, (int)start.y, (int)end.x, (int)end.y, color); } public static void DrawLine(this Texture2D texture, Vector2 start, Vector2 end, Color color) { Line(texture, (int)start.x, (int)start.y, (int)end.x, (int)end.y, color); } /// /// Draws a line between two points. Implementation of Bresenham's line algorithm. /// /// x of the start point /// y of the start point /// x of the end point /// y of the end point public static void DrawLine(this Texture2D texture, int x0, int y0, int x1, int y1, Color color) { Line(texture, x0, y0, x1, y1, color); } private static void Line(Texture2D texture, int x0, int y0, int x1, int y1, Color color) { int width = texture.width; int height = texture.height; bool isSteep = Math.Abs(y1 - y0) > Math.Abs(x1 - x0); if (isSteep) { Swap(ref x0, ref y0); Swap(ref x1, ref y1); } if (x0 > x1) { Swap(ref x0, ref x1); Swap(ref y0, ref y1); } int deltax = x1 - x0; int deltay = Math.Abs(y1 - y0); int error = deltax / 2; int ystep; int y = y0; if (y0 < y1) ystep = 1; else ystep = -1; for (int x = x0; x < x1; x++) { if (isSteep) texture.DrawPixel(y, x, width, height, color); else texture.DrawPixel(x, y, width, height, color); error = error - deltay; if (error < 0) { y = y + ystep; error = error + deltax; } } } /// /// Swap two ints by reference. /// private static void Swap(ref int x, ref int y) { int temp = x; x = y; y = temp; } /// /// Transforms a point in the texture plane so that 0,0 points at left-top corner. private static int TransformToLeftTop_y(int y, int height) { return height - y; } /// /// Transforms a point in the texture plane so that 0,0 points at left-top corner. private static int TransformToLeftTop_y(float y, int height) { return height - (int)y; } } } ================================================ FILE: SGFUnity/Extension/TransformExtensions.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using Object = UnityEngine.Object; public static class TransformExtensions { #region Position /// /// Sets the X position of this transform. /// public static void SetX(this Transform transform, float x) { var newPosition = new Vector3(x, transform.position.y, transform.position.z); transform.position = newPosition; } /// /// Sets the Y position of this transform. /// public static void SetY(this Transform transform, float y) { var newPosition = new Vector3(transform.position.x, y, transform.position.z); transform.position = newPosition; } /** Sets the Z position of this transform. */ public static void SetZ(this Transform transform, float z) { var newPosition = new Vector3(transform.position.x, transform.position.y, z); transform.position = newPosition; } /** Sets the X and Y position of this transform. */ public static void SetXY(this Transform transform, float x, float y) { var newPosition = new Vector3(x, y, transform.position.z); transform.position = newPosition; } /** Sets the X and Z position of this transform. */ public static void SetXZ(this Transform transform, float x, float z) { var newPosition = new Vector3(x, transform.position.y, z); transform.position = newPosition; } /** Sets the Y and Z position of this transform. */ public static void SetYZ(this Transform transform, float y, float z) { var newPosition = new Vector3(transform.position.x, y, z); transform.position = newPosition; } /** Sets the X, Y and Z position of this transform. */ public static void SetXYZ(this Transform transform, float x, float y, float z) { var newPosition = new Vector3(x, y, z); transform.position = newPosition; } /** Translates this transform along the X axis. */ public static void TranslateX(this Transform transform, float x) { var offset = new Vector3(x, 0, 0); transform.position += offset; } /** Translates this transform along the Y axis. */ public static void TranslateY(this Transform transform, float y) { var offset = new Vector3(0, y, 0); transform.position += offset; } /** Translates this transform along the Z axis. */ public static void TranslateZ(this Transform transform, float z) { var offset = new Vector3(0, 0, z); transform.position += offset; } /** Translates this transform along the X and Y axes. */ public static void TranslateXY(this Transform transform, float x, float y) { var offset = new Vector3(x, y, 0); transform.position += offset; } /** Translates this transform along the X and Z axes. */ public static void TranslateXZ(this Transform transform, float x, float z) { var offset = new Vector3(x, 0, z); transform.position += offset; } /** Translates this transform along the Y and Z axes. */ public static void TranslateYZ(this Transform transform, float y, float z) { var offset = new Vector3(0, y, z); transform.position += offset; } /** Translates this transform along the X, Y and Z axis. */ public static void TranslateXYZ(this Transform transform, float x, float y, float z) { var offset = new Vector3(x, y, z); transform.position += offset; } /** Sets the local X position of this transform. */ public static void SetLocalX(this Transform transform, float x) { var newPosition = new Vector3(x, transform.localPosition.y, transform.localPosition.z); transform.localPosition = newPosition; } /** Sets the local Y position of this transform. */ public static void SetLocalY(this Transform transform, float y) { var newPosition = new Vector3(transform.localPosition.x, y, transform.localPosition.z); transform.localPosition = newPosition; } /** Sets the local Z position of this transform. */ public static void SetLocalZ(this Transform transform, float z) { var newPosition = new Vector3(transform.localPosition.x, transform.localPosition.y, z); transform.localPosition = newPosition; } /** Sets the local X and Y position of this transform. */ public static void SetLocalXY(this Transform transform, float x, float y) { var newPosition = new Vector3(x, y, transform.localPosition.z); transform.localPosition = newPosition; } /** Sets the local X and Z position of this transform. */ public static void SetLocalXZ(this Transform transform, float x, float z) { var newPosition = new Vector3(x, transform.localPosition.z, z); transform.localPosition = newPosition; } /** Sets the local Y and Z position of this transform. */ public static void SetLocalYZ(this Transform transform, float y, float z) { var newPosition = new Vector3(transform.localPosition.x, y, z); transform.localPosition = newPosition; } /** Sets the local X, Y and Z position of this transform. */ public static void SetLocalXYZ(this Transform transform, float x, float y, float z) { var newPosition = new Vector3(x, y, z); transform.localPosition = newPosition; } /** Sets the position to 0, 0, 0. */ public static void ResetPosition(this Transform transform) { transform.position = Vector3.zero; } /** Sets the local position to 0, 0, 0. */ public static void ResetLocalPosition(this Transform transform) { transform.localPosition = Vector3.zero; } #endregion #region Scale /** Sets the local X scale of this transform. */ public static void SetScaleX(this Transform transform, float x) { var newScale = new Vector3(x, transform.localScale.y, transform.localScale.z); transform.localScale = newScale; } /** Sets the local Y scale of this transform. */ public static void SetScaleY(this Transform transform, float y) { var newScale = new Vector3(transform.localScale.x, y, transform.localScale.z); transform.localScale = newScale; } /** Sets the local Z scale of this transform. */ public static void SetScaleZ(this Transform transform, float z) { var newScale = new Vector3(transform.localScale.x, transform.localScale.y, z); transform.localScale = newScale; } /** Sets the local X and Y scale of this transform. */ public static void SetScaleXY(this Transform transform, float x, float y) { var newScale = new Vector3(x, y, transform.localScale.z); transform.localScale = newScale; } /** Sets the local X and Z scale of this transform. */ public static void SetScaleXZ(this Transform transform, float x, float z) { var newScale = new Vector3(x, transform.localScale.y, z); transform.localScale = newScale; } /** Sets the local Y and Z scale of this transform. */ public static void SetScaleYZ(this Transform transform, float y, float z) { var newScale = new Vector3(transform.localScale.x, y, z); transform.localScale = newScale; } /** Sets the local X, Y and Z scale of this transform. */ public static void SetScaleXYZ(this Transform transform, float x, float y, float z) { var newScale = new Vector3(x, y, z); transform.localScale = newScale; } /** Scale this transform in the X direction. */ public static void ScaleByX(this Transform transform, float x) { transform.localScale = new Vector3(transform.localScale.x * x, transform.localScale.y, transform.localScale.z); } /** Scale this transform in the Y direction. */ public static void ScaleByY(this Transform transform, float y) { transform.localScale = new Vector3(transform.localScale.x, transform.localScale.y * y, transform.localScale.z); } /** Scale this transform in the Z direction. */ public static void ScaleByZ(this Transform transform, float z) { transform.localScale = new Vector3(transform.localScale.x, transform.localScale.y, transform.localScale.z * z); } /** Scale this transform in the X, Y direction. */ public static void ScaleByXY(this Transform transform, float x, float y) { transform.localScale = new Vector3(transform.localScale.x * x, transform.localScale.y * y, transform.localScale.z); } /** Scale this transform in the X, Z directions. */ public static void ScaleByXZ(this Transform transform, float x, float z) { transform.localScale = new Vector3(transform.localScale.x * x, transform.localScale.y, transform.localScale.z * z); } /** Scale this transform in the Y and Z directions. */ public static void ScaleByYZ(this Transform transform, float y, float z) { transform.localScale = new Vector3(transform.localScale.x, transform.localScale.y * y, transform.localScale.z * z); } /** Scale this transform in the X and Y directions. */ public static void ScaleByXY(this Transform transform, float r) { transform.ScaleByXY(r, r); } /** Scale this transform in the X and Z directions. */ public static void ScaleByXZ(this Transform transform, float r) { transform.ScaleByXZ(r, r); } /** Scale this transform in the Y and Z directions. */ public static void ScaleByYZ(this Transform transform, float r) { transform.ScaleByYZ(r, r); } /** Scale this transform in the X, Y and Z directions. */ public static void ScaleByXYZ(this Transform transform, float x, float y, float z) { transform.localScale = new Vector3( x, y, z); } /** Scale this transform in the X, Y and Z directions. */ public static void ScaleByXYZ(this Transform transform, float r) { transform.ScaleByXYZ(r, r, r); } /** Resets the local scale of this transform in to 1 1 1. */ public static void ResetScale(this Transform transform) { transform.localScale = Vector3.one; } #endregion #region FlipScale /** Negates the X scale. */ public static void FlipX(this Transform transform) { transform.SetScaleX(-transform.localScale.x); } /** Negates the Y scale. */ public static void FlipY(this Transform transform) { transform.SetScaleY(-transform.localScale.y); } /** Negates the Z scale. */ public static void FlipZ(this Transform transform) { transform.SetScaleZ(-transform.localScale.z); } /** Negates the X and Y scale. */ public static void FlipXY(this Transform transform) { transform.SetScaleXY(-transform.localScale.x, -transform.localScale.y); } /** Negates the X and Z scale. */ public static void FlipXZ(this Transform transform) { transform.SetScaleXZ(-transform.localScale.x, -transform.localScale.z); } /** Negates the Y and Z scale. */ public static void FlipYZ(this Transform transform) { transform.SetScaleYZ(-transform.localScale.y, -transform.localScale.z); } /** Negates the X, Y and Z scale. */ public static void FlipXYZ(this Transform transform) { transform.SetScaleXYZ(-transform.localScale.z, -transform.localScale.y, -transform.localScale.z); } /** Sets all scale values to the absolute values. */ public static void FlipPostive(this Transform transform) { transform.localScale = new Vector3( Mathf.Abs(transform.localScale.x), Mathf.Abs(transform.localScale.y), Mathf.Abs(transform.localScale.z)); } #endregion #region Rotation /** Rotates the transform around the X axis. */ public static void RotateAroundX(this Transform transform, float angle) { var rotation = new Vector3(angle, 0, 0); transform.Rotate(rotation); } /** Rotates the transform around the Y axis. */ public static void RotateAroundY(this Transform transform, float angle) { var rotation = new Vector3(0, angle, 0); transform.Rotate(rotation); } /** Rotates the transform around the Z axis. */ public static void RotateAroundZ(this Transform transform, float angle) { var rotation = new Vector3(0, 0, angle); transform.Rotate(rotation); } /** Sets the X rotation. */ public static void SetRotationX(this Transform transform, float angle) { transform.eulerAngles = new Vector3(angle, 0, 0); } /** Sets the Y rotation. */ public static void SetRotationY(this Transform transform, float angle) { transform.eulerAngles = new Vector3(0, angle, 0); } /** Sets the Z rotation. */ public static void SetRotationZ(this Transform transform, float angle) { transform.eulerAngles = new Vector3(0, 0, angle); } /** Sets the local X rotation. */ public static void SetLocalRotationX(this Transform transform, float angle) { transform.localRotation = Quaternion.Euler(new Vector3(angle, 0, 0)); } /** Sets the local Y rotation. */ public static void SetLocalRotationY(this Transform transform, float angle) { transform.localRotation = Quaternion.Euler(new Vector3(0, angle, 0)); } /** Sets the local Z rotation. */ public static void SetLocalRotationZ(this Transform transform, float angle) { transform.localRotation = Quaternion.Euler(new Vector3(0, 0, angle)); } /** Resets the rotation to 0, 0, 0. */ public static void ResetRotation(this Transform transform) { transform.rotation = Quaternion.identity; } /** Resets the local rotation to 0, 0, 0. */ public static void ResetLocalRotation(this Transform transform) { transform.localRotation = Quaternion.identity; } #endregion #region All /** Resets the ;local position, local rotation, and local scale. */ public static void ResetLocal(this Transform transform) { transform.ResetLocalRotation(); transform.ResetLocalPosition(); transform.ResetScale(); } /** Resets the position, rotation, and local scale. */ public static void Reset(this Transform transform) { transform.ResetRotation(); transform.ResetPosition(); transform.ResetScale(); } #endregion #region Children public static void DestroyChildren(this Transform transform) { //Add children to list before destroying //otherwise GetChild(i) may bomb out var children = new List(); for (var i = 0; i < transform.childCount; i++) { var child = transform.GetChild(i); children.Add(child); } foreach (var child in children) { Object.Destroy(child.gameObject); } } public static void DestroyChildrenImmediate(this Transform transform) { //Add children to list before destroying //otherwise GetChild(i) may bomb out var children = new List(); for (var i = 0; i < transform.childCount; i++) { var child = transform.GetChild(i); children.Add(child); } foreach (var child in children) { Object.DestroyImmediate(child.gameObject); } } public static List GetChildren(this Transform transform) { var children = new List(); for (var i = 0; i < transform.childCount; i++) { var child = transform.GetChild(i); children.Add(child); } return children; } public static void Sort(this Transform transform, Func sortFunction) { var children = transform.GetChildren(); var sortedChildren = children.OrderBy(sortFunction).ToList(); for (int i = 0; i < sortedChildren.Count(); i++) { sortedChildren[i].SetSiblingIndex(i); } } public static void SortAlphabetically(this Transform transform) { transform.Sort(t => t.name); } /** A lazy enumerable of this objects transform, and all it's children down the hierarchy. @version_e_1_1 */ public static IEnumerable SelfAndAllChildren(this Transform transform) { var openList = new Queue(); openList.Enqueue(transform); while (openList.Any()) { var currentChild = openList.Dequeue(); yield return currentChild; var children = transform.GetChildren(); foreach (var child in children) { openList.Enqueue(child); } } } #endregion public static T FindComponent(this Transform transform, string name) { var tmp = transform.Find(name); if (tmp != null) return tmp.GetComponent(); return default(T); } } ================================================ FILE: SGFUnity/Extension/VectorExtensions.cs ================================================ using UnityEngine; public static class VectorExtensions { public static Vector3 To3DXZ(this Vector2 vector, float y) { return new Vector3(vector.x, y, vector.y); } public static Vector3 To3DXZ(this Vector2 vector) { return vector.To3DXZ(0); } public static Vector3 To3DXY(this Vector2 vector, float z) { return new Vector3(vector.x, vector.y, z); } public static Vector3 To3DXY(this Vector2 vector) { return vector.To3DXY(0); } public static Vector3 To3DYZ(this Vector2 vector, float x) { return new Vector3(x, vector.x, vector.y); } public static Vector3 To3DYZ(this Vector2 vector) { return vector.To3DYZ(0); } public static Vector2 To2DXZ(this Vector3 vector) { return new Vector2(vector.x, vector.z); } public static Vector2 To2DXY(this Vector3 vector) { return new Vector2(vector.x, vector.y); } public static Vector2 To2DYZ(this Vector3 vector) { return new Vector2(vector.y, vector.z); } /** Returns the vector rotated 90 degrees counter-clockwise. This vector is always perpendicular to the given vector. The perp dot product can be caluclted using this: var perpDotPorpduct = Vector2.Dot(v1.Perp(), v2); */ public static Vector2 Perp(this Vector2 vector) { return new Vector2(-vector.y, vector.x); } /** Returns the projection of this vector onto the given base. */ public static Vector2 Proj(this Vector2 vector, Vector2 baseVector) { var direction = baseVector.normalized; var magnitude = Vector2.Dot(vector, direction); return direction * magnitude; } /** Returns the rejection of this vector onto the given base. The sum of a vector's projection and rejection on a base is equal to the original vector. */ public static Vector2 Rej(this Vector2 vector, Vector2 baseVector) { return vector - vector.Proj(baseVector); } /** Returns the projection of this vector onto the given base. */ public static Vector3 Proj(this Vector3 vector, Vector3 baseVector) { var direction = baseVector.normalized; var magnitude = Vector2.Dot(vector, direction); return direction * magnitude; } /** Returns the rejection of this vector onto the given base. The sum of a vector's projection and rejection on a base is equal to the original vector. */ public static Vector3 Rej(this Vector3 vector, Vector3 baseVector) { return vector - vector.Proj(baseVector); } /** Returns the projection of this vector onto the given base. */ public static Vector4 Proj(this Vector4 vector, Vector4 baseVector) { var direction = baseVector.normalized; var magnitude = Vector2.Dot(vector, direction); return direction * magnitude; } /** Returns the rejection of this vector onto the given base. The sum of a vector's projection and rejection on a base is equal to the original vector. */ public static Vector4 Rej(this Vector4 vector, Vector4 baseVector) { return vector - vector.Proj(baseVector); } public static Vector3 PerpXZ(this Vector3 v) { return new Vector3(-v.z, v.y, v.x); } public static Vector3 PerpXY(this Vector3 v) { return new Vector3(-v.y, v.x, v.z); } public static string GetStringValue(this Vector3 v) { return v.x + "," + v.y + "," + v.z; } public static void SetStringValue(this Vector3 v, string strValue) { string[] tmp = strValue.Split(','); if (tmp.Length >= 3) { float x = v.x; float y = v.y; float z = v.z; float.TryParse(tmp[0], out x); float.TryParse(tmp[1], out y); float.TryParse(tmp[2], out z); v.x = x; v.y = y; v.z = z; } } } ================================================ FILE: SGFUnity/ILR/DebugerILR/DebugerMethodRedirector.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Reflection; using ILRuntime.CLR.Method; using ILRuntime.CLR.Utils; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Stack; using AppDomain = ILRuntime.Runtime.Enviorment.AppDomain; namespace SGF.Unity.ILR.DebugerILR { public unsafe class DebugerMethodRedirector:ICLRMethodRedirector { public const string Prefix = "ILR> "; public void Init(AppDomain app) { BindingFlags flag = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; MethodBase method; FieldInfo field; Type[] args; Type type = typeof(SGF.Debuger); args = new Type[] { typeof(System.String) }; method = type.GetMethod("Log", flag, null, args, null); app.RegisterCLRMethodRedirection(method, Log_1); args = new Type[] { typeof(System.String), typeof(System.Object[]) }; method = type.GetMethod("Log", flag, null, args, null); app.RegisterCLRMethodRedirection(method, Log_2); args = new Type[] { typeof(SGF.ILogTag), typeof(System.String) }; method = type.GetMethod("Log", flag, null, args, null); app.RegisterCLRMethodRedirection(method, Log_3); args = new Type[] { typeof(SGF.ILogTag), typeof(System.String), typeof(System.Object[]) }; method = type.GetMethod("Log", flag, null, args, null); app.RegisterCLRMethodRedirection(method, Log_4); args = new Type[] { typeof(System.String) }; method = type.GetMethod("LogWarning", flag, null, args, null); app.RegisterCLRMethodRedirection(method, LogWarning_5); args = new Type[] { typeof(System.String), typeof(System.Object[]) }; method = type.GetMethod("LogWarning", flag, null, args, null); app.RegisterCLRMethodRedirection(method, LogWarning_6); args = new Type[] { typeof(SGF.ILogTag), typeof(System.String) }; method = type.GetMethod("LogWarning", flag, null, args, null); app.RegisterCLRMethodRedirection(method, LogWarning_7); args = new Type[] { typeof(SGF.ILogTag), typeof(System.String), typeof(System.Object[]) }; method = type.GetMethod("LogWarning", flag, null, args, null); app.RegisterCLRMethodRedirection(method, LogWarning_8); args = new Type[] { typeof(System.String) }; method = type.GetMethod("LogError", flag, null, args, null); app.RegisterCLRMethodRedirection(method, LogError_9); args = new Type[] { typeof(System.String), typeof(System.Object[]) }; method = type.GetMethod("LogError", flag, null, args, null); app.RegisterCLRMethodRedirection(method, LogError_10); args = new Type[] { typeof(SGF.ILogTag), typeof(System.String) }; method = type.GetMethod("LogError", flag, null, args, null); app.RegisterCLRMethodRedirection(method, LogError_11); args = new Type[] { typeof(SGF.ILogTag), typeof(System.String), typeof(System.Object[]) }; method = type.GetMethod("LogError", flag, null, args, null); app.RegisterCLRMethodRedirection(method, LogError_12); } static StackObject* Log_1(ILIntepreter __intp, StackObject* __esp, IList __mStack, CLRMethod __method, bool isNewObj) { ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain; StackObject* ptr_of_this_method; StackObject* __ret = ILIntepreter.Minus(__esp, 1); ptr_of_this_method = ILIntepreter.Minus(__esp, 1); System.String message = (System.String)typeof(System.String).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); StackFrame frame = __intp.Stack.Frames.Peek(); var caller = frame.Method.DeclearingType.Name + "::" + frame.Method.Name + "() "; SGF.Debuger.Internal_Log(Prefix + caller + message); return __ret; } static StackObject* Log_2(ILIntepreter __intp, StackObject* __esp, IList __mStack, CLRMethod __method, bool isNewObj) { ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain; StackObject* ptr_of_this_method; StackObject* __ret = ILIntepreter.Minus(__esp, 2); ptr_of_this_method = ILIntepreter.Minus(__esp, 1); System.Object[] args = (System.Object[])typeof(System.Object[]).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); ptr_of_this_method = ILIntepreter.Minus(__esp, 2); System.String format = (System.String)typeof(System.String).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); StackFrame frame = __intp.Stack.Frames.Peek(); var caller = frame.Method.DeclearingType.Name + "::" + frame.Method.Name + "() "; SGF.Debuger.Internal_Log(Prefix + caller + string.Format(format, args)); return __ret; } static StackObject* Log_3(ILIntepreter __intp, StackObject* __esp, IList __mStack, CLRMethod __method, bool isNewObj) { ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain; StackObject* ptr_of_this_method; StackObject* __ret = ILIntepreter.Minus(__esp, 2); ptr_of_this_method = ILIntepreter.Minus(__esp, 1); System.String message = (System.String)typeof(System.String).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); ptr_of_this_method = ILIntepreter.Minus(__esp, 2); SGF.ILogTag obj = (SGF.ILogTag)typeof(SGF.ILogTag).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); StackFrame frame = __intp.Stack.Frames.Peek(); var caller = obj.LOG_TAG + "::" + frame.Method.Name + "() "; SGF.Debuger.Internal_Log(Prefix + caller + message); return __ret; } static StackObject* Log_4(ILIntepreter __intp, StackObject* __esp, IList __mStack, CLRMethod __method, bool isNewObj) { ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain; StackObject* ptr_of_this_method; StackObject* __ret = ILIntepreter.Minus(__esp, 3); ptr_of_this_method = ILIntepreter.Minus(__esp, 1); System.Object[] args = (System.Object[])typeof(System.Object[]).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); ptr_of_this_method = ILIntepreter.Minus(__esp, 2); System.String format = (System.String)typeof(System.String).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); ptr_of_this_method = ILIntepreter.Minus(__esp, 3); SGF.ILogTag obj = (SGF.ILogTag)typeof(SGF.ILogTag).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); StackFrame frame = __intp.Stack.Frames.Peek(); var caller = obj.LOG_TAG + "::" + frame.Method.Name + "() "; SGF.Debuger.Internal_Log(Prefix + caller + string.Format(format, args)); return __ret; } static StackObject* LogWarning_5(ILIntepreter __intp, StackObject* __esp, IList __mStack, CLRMethod __method, bool isNewObj) { ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain; StackObject* ptr_of_this_method; StackObject* __ret = ILIntepreter.Minus(__esp, 1); ptr_of_this_method = ILIntepreter.Minus(__esp, 1); System.String message = (System.String)typeof(System.String).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); StackFrame frame = __intp.Stack.Frames.Peek(); var caller = frame.Method.DeclearingType.Name + "::" + frame.Method.Name + "() "; SGF.Debuger.Internal_LogWarning(Prefix + caller + message); return __ret; } static StackObject* LogWarning_6(ILIntepreter __intp, StackObject* __esp, IList __mStack, CLRMethod __method, bool isNewObj) { ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain; StackObject* ptr_of_this_method; StackObject* __ret = ILIntepreter.Minus(__esp, 2); ptr_of_this_method = ILIntepreter.Minus(__esp, 1); System.Object[] args = (System.Object[])typeof(System.Object[]).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); ptr_of_this_method = ILIntepreter.Minus(__esp, 2); System.String format = (System.String)typeof(System.String).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); StackFrame frame = __intp.Stack.Frames.Peek(); var caller = frame.Method.DeclearingType.Name + "::" + frame.Method.Name + "() "; SGF.Debuger.Internal_LogWarning(Prefix + caller + string.Format(format, args)); return __ret; } static StackObject* LogWarning_7(ILIntepreter __intp, StackObject* __esp, IList __mStack, CLRMethod __method, bool isNewObj) { ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain; StackObject* ptr_of_this_method; StackObject* __ret = ILIntepreter.Minus(__esp, 2); ptr_of_this_method = ILIntepreter.Minus(__esp, 1); System.String message = (System.String)typeof(System.String).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); ptr_of_this_method = ILIntepreter.Minus(__esp, 2); SGF.ILogTag obj = (SGF.ILogTag)typeof(SGF.ILogTag).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); StackFrame frame = __intp.Stack.Frames.Peek(); var caller = obj.LOG_TAG + "::" + frame.Method.Name + "() "; SGF.Debuger.Internal_LogWarning(Prefix + caller + message); return __ret; } static StackObject* LogWarning_8(ILIntepreter __intp, StackObject* __esp, IList __mStack, CLRMethod __method, bool isNewObj) { ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain; StackObject* ptr_of_this_method; StackObject* __ret = ILIntepreter.Minus(__esp, 3); ptr_of_this_method = ILIntepreter.Minus(__esp, 1); System.Object[] args = (System.Object[])typeof(System.Object[]).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); ptr_of_this_method = ILIntepreter.Minus(__esp, 2); System.String format = (System.String)typeof(System.String).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); ptr_of_this_method = ILIntepreter.Minus(__esp, 3); SGF.ILogTag obj = (SGF.ILogTag)typeof(SGF.ILogTag).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); StackFrame frame = __intp.Stack.Frames.Peek(); var caller = obj.LOG_TAG + "::" + frame.Method.Name + "() "; SGF.Debuger.Internal_LogWarning(Prefix + caller + string.Format(format, args)); return __ret; } static StackObject* LogError_9(ILIntepreter __intp, StackObject* __esp, IList __mStack, CLRMethod __method, bool isNewObj) { ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain; StackObject* ptr_of_this_method; StackObject* __ret = ILIntepreter.Minus(__esp, 1); ptr_of_this_method = ILIntepreter.Minus(__esp, 1); System.String message = (System.String)typeof(System.String).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); var stacktrace = __domain.DebugService.GetStackTrance(__intp); StackFrame frame = __intp.Stack.Frames.Peek(); var caller = frame.Method.DeclearingType.Name + "::" + frame.Method.Name + "() "; SGF.Debuger.Internal_LogError(Prefix + caller + message + "\n" + stacktrace); return __ret; } static StackObject* LogError_10(ILIntepreter __intp, StackObject* __esp, IList __mStack, CLRMethod __method, bool isNewObj) { ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain; StackObject* ptr_of_this_method; StackObject* __ret = ILIntepreter.Minus(__esp, 2); ptr_of_this_method = ILIntepreter.Minus(__esp, 1); System.Object[] args = (System.Object[])typeof(System.Object[]).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); ptr_of_this_method = ILIntepreter.Minus(__esp, 2); System.String format = (System.String)typeof(System.String).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); var stacktrace = __domain.DebugService.GetStackTrance(__intp); StackFrame frame = __intp.Stack.Frames.Peek(); var caller = frame.Method.DeclearingType.Name + "::" + frame.Method.Name + "() "; SGF.Debuger.Internal_LogError(Prefix + caller + string.Format(format, args) + "\n" + stacktrace); return __ret; } static StackObject* LogError_11(ILIntepreter __intp, StackObject* __esp, IList __mStack, CLRMethod __method, bool isNewObj) { ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain; StackObject* ptr_of_this_method; StackObject* __ret = ILIntepreter.Minus(__esp, 2); ptr_of_this_method = ILIntepreter.Minus(__esp, 1); System.String message = (System.String)typeof(System.String).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); ptr_of_this_method = ILIntepreter.Minus(__esp, 2); SGF.ILogTag obj = (SGF.ILogTag)typeof(SGF.ILogTag).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); var stacktrace = __domain.DebugService.GetStackTrance(__intp); StackFrame frame = __intp.Stack.Frames.Peek(); var caller = obj.LOG_TAG + "::" + frame.Method.Name + "() "; SGF.Debuger.Internal_LogError(Prefix + caller + message + "\n" + stacktrace); return __ret; } static StackObject* LogError_12(ILIntepreter __intp, StackObject* __esp, IList __mStack, CLRMethod __method, bool isNewObj) { ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain; StackObject* ptr_of_this_method; StackObject* __ret = ILIntepreter.Minus(__esp, 3); ptr_of_this_method = ILIntepreter.Minus(__esp, 1); System.Object[] args = (System.Object[])typeof(System.Object[]).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); ptr_of_this_method = ILIntepreter.Minus(__esp, 2); System.String format = (System.String)typeof(System.String).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); ptr_of_this_method = ILIntepreter.Minus(__esp, 3); SGF.ILogTag obj = (SGF.ILogTag)typeof(SGF.ILogTag).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack)); __intp.Free(ptr_of_this_method); var stacktrace = __domain.DebugService.GetStackTrance(__intp); StackFrame frame = __intp.Stack.Frames.Peek(); var caller = obj.LOG_TAG + "::" + frame.Method.Name + "() "; SGF.Debuger.Internal_LogError(Prefix + caller + string.Format(format, args) + "\n" + stacktrace); return __ret; } } } ================================================ FILE: SGFUnity/ILR/DebugerILR/ILogTagAdaptor.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; using AppDomain = ILRuntime.Runtime.Enviorment.AppDomain; namespace SGF.Unity.ILR.DebugerILR { public class ILogTagAdaptor:CrossBindingAdaptor { public override object CreateCLRInstance(AppDomain appdomain, ILTypeInstance instance) { return new Adaptor(appdomain, instance); } public override Type BaseCLRType { get { return typeof(ILogTag); } } public override Type AdaptorType { get { return typeof(Adaptor); } } class Adaptor : ILogTag, CrossBindingAdaptorType { private AppDomain m_appdomain; public ILTypeInstance ILInstance { get; private set; } public Adaptor(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance) { m_appdomain = appdomain; ILInstance = instance; } private IMethod mGetLogTag; private bool isGetLogTagInvoking = false; public string LOG_TAG { get { if (mGetLogTag == null) { mGetLogTag = ILInstance.Type.GetMethod("get_LOG_TAG", 0); } if (mGetLogTag != null && !isGetLogTagInvoking) { isGetLogTagInvoking = true; var result = m_appdomain.Invoke(mGetLogTag, ILInstance) as string; isGetLogTagInvoking = false; return result; } return ""; } } } } } ================================================ FILE: SGFUnity/ILR/DelegateConvertor.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using AppDomain = ILRuntime.Runtime.Enviorment.AppDomain; namespace SGF.Unity.ILR { public class DelegateConvertor { public static void Init(AppDomain appdomain) { appdomain.DelegateManager.RegisterMethodDelegate(); appdomain.DelegateManager.RegisterMethodDelegate(); appdomain.DelegateManager.RegisterMethodDelegate(); appdomain.DelegateManager.RegisterMethodDelegate(); } } } ================================================ FILE: SGFUnity/ILR/ILRManager.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * ILR管理器 * 用来实现原生模块与ILR模块的无缝衔接 * 你在用模块管理器管理模块时,不需要关心该模块是ILR的,还是原生的 * ILR Manager  * It is used to realize the seamless connection between the native module and the ILR module  * When you manage the module with the module manager, you don't need to care if the module is ILR or native * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.IO; using System.Reflection; using ILRuntime.CLR.TypeSystem; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; using Mono.Cecil.Pdb; using SGF.Utils; using AppDomain = ILRuntime.Runtime.Enviorment.AppDomain; using SGF.Extension; using SGF.Unity.ILR.DebugerILR; using SGF.Unity.ILR.ModuleILR; using SGF.Unity.ILR.UIILR; namespace SGF.Unity.ILR { public interface ICLRMethodRedirector { void Init(AppDomain app); } public enum RunMode { Script = 0, Native = 1 } public class ILRManager:Singleton { public RunMode RunMode { get; private set; } public bool UsePdb { get; private set; } private List m_listSearchDir = new List(); private AppDomain m_appdomain; private List m_listNativeAssembly = new List(); public static object CreateInstance(string typeName, string assemblyName = "", params object[] args) { return Instance.CreateInstanceInternal(typeName, assemblyName, args); } public static object CreateInstance(string typeName, params object[] args) { return Instance.CreateInstanceInternal(typeName, "", args); } public static object CreateInstance(string typeName) { return Instance.CreateInstanceInternal(typeName, "", null); } //====================================================================================== public void Init(RunMode runMode, bool usePdb) { Debuger.Log("RunMode:{0}, UsePdb:{1}", runMode, usePdb); RunMode = runMode; UsePdb = usePdb; //首先实例化ILRuntime的AppDomain,AppDomain是一个应用程序域,每个AppDomain都是一个独立的沙盒 m_appdomain = new AppDomain(); if (runMode == RunMode.Script) { //注册Adaptor RegisterCrossBindingAdaptor(new ILogTagAdaptor()); RegisterCrossBindingAdaptor(new GeneralModuleAdaptor()); RegisterCrossBindingAdaptor(new ILRUILoadingAdaptor()); RegisterCrossBindingAdaptor(new ILRUIPageAdaptor()); RegisterCrossBindingAdaptor(new ILRUIWindowAdaptor()); RegisterCrossBindingAdaptor(new ILRUIWidgetAdaptor()); RegisterCrossBindingAdaptor(new ILRUIPanelAdaptor()); //注册重定向器 RegisterCLRMethodRedirector(new DebugerMethodRedirector()); } } public void Clean() { Debuger.Log(); if (m_appdomain != null) { m_appdomain = null; } m_listNativeAssembly.Clear(); } //======================================================================== //注册函数 //======================================================================== public void RegisterCrossBindingAdaptor(CrossBindingAdaptor adaptor) { if (m_appdomain != null) { m_appdomain.RegisterCrossBindingAdaptor(adaptor); } else { Debuger.LogError("ILRuntime的AppDomain未创建!"); } } public void RegisterCLRMethodRedirector(ICLRMethodRedirector redirector) { if (m_appdomain != null) { if (redirector != null) { redirector.Init(m_appdomain); } } else { Debuger.LogError("ILRuntime的AppDomain未创建!"); } } //======================================================================== //加载Assembly //======================================================================== #region 加载Assembly相关函数 public void AddSearchDirectory(string path) { Debuger.Log(path); if (!m_listSearchDir.Contains(path)) { m_listSearchDir.Add(path); } } private string FindAssemblyFullPath(string assemblyName) { for (int i = 0; i < m_listSearchDir.Count; i++) { string path = m_listSearchDir[i] + "/" + assemblyName + ".dll"; if (File.Exists(path)) { return path; } } return null; } public void LoadAssembly(string assemblyName) { if (RunMode == RunMode.Native) { LoadAssemblyNative(assemblyName); } else { LoadAssemblyScript(assemblyName); } } private void LoadAssemblyNative(string assemblyName) { Debuger.Log(assemblyName); string dllPath = FindAssemblyFullPath(assemblyName); if (string.IsNullOrEmpty(dllPath)) { Debuger.LogError("Assembly不存在:{0}", assemblyName); return; } Assembly assembly = Assembly.LoadFile(dllPath); if (assembly != null) { m_listNativeAssembly.Add(assembly); } } private void LoadAssemblyScript(string assemblyName) { Debuger.Log(assemblyName); string dllPath = FindAssemblyFullPath(assemblyName); if (string.IsNullOrEmpty(dllPath)) { Debuger.LogError("Assembly不存在:{0}", assemblyName); return; } byte[] dllBytes = FileUtils.ReadFile(dllPath); byte[] pdbBytes = null; if (UsePdb) { pdbBytes = FileUtils.ReadFile(GetPdbPath(dllPath)); } try { using (MemoryStream dll = new MemoryStream(dllBytes)) { if (pdbBytes != null) { using (MemoryStream pdb = new MemoryStream(pdbBytes)) { Debuger.Log("LoadAssembly"); m_appdomain.LoadAssembly(dll, pdb, new PdbReaderProvider()); } } else { Debuger.Log("LoadAssembly"); m_appdomain.LoadAssembly(dll, null, null); } } } catch (Exception e) { Debuger.LogError(e.Message); } } private string GetPdbPath(string dllPath) { int i = dllPath.LastIndexOf(".dll"); return dllPath.Substring(0, i) + ".pdb"; } #endregion //======================================================================== //获取类型 //======================================================================== private Type GetNativeType(string typeName) { Type type = null; for (int i = 0; i < m_listNativeAssembly.Count; i++) { type = m_listNativeAssembly[i].GetType(typeName); if (type != null) { break; } } return type; } private IType GetScriptType(string typeName) { IType type = m_appdomain.GetType(typeName); return type; } //======================================================================== //函数调用 //======================================================================== public object Invoke(string typeName, string methodName, params object[] args) { Debuger.Log("{0}::{1}({2})", typeName, methodName, args.ToListString()); if (RunMode == RunMode.Native) { Type type = GetNativeType(typeName); if (type != null) { MethodInfo mi = type.GetMethod(methodName); if (mi != null) { return mi.Invoke(null, args); } else { Debuger.LogError("从NativeAssembly中找不到该函数!"); } } else { Debuger.LogError("从NativeAssembly中找不到该类型!"); } } else { return m_appdomain.Invoke(typeName, methodName, null, args); } return null; } //======================================================================== //创建实例 //======================================================================== private object CreateInstanceInternal(string typeName, string assemblyName, object[] args) { if (RunMode == RunMode.Native) { if (string.IsNullOrEmpty(assemblyName)) { return System.AppDomain.CurrentDomain.GetType().Assembly.CreateInstance(typeName); } else { Type type = Type.GetType(typeName + "," + assemblyName); if (type != null) { return Activator.CreateInstance(type, args); } } } else { ILTypeInstance obj = m_appdomain.Instantiate(typeName, args); if (obj != null) { return obj.CLRInstance; } } Debuger.LogError("找不到类型:" + typeName); return null; } } } ================================================ FILE: SGFUnity/ILR/ModuleILR/GeneralModuleAdaptor.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; using SGF.Module; using AppDomain = ILRuntime.Runtime.Enviorment.AppDomain; namespace SGF.Unity.ILR.ModuleILR { public class GeneralModuleAdaptor:CrossBindingAdaptor { public override object CreateCLRInstance(AppDomain appdomain, ILTypeInstance instance) { return new Adaptor(appdomain, instance); } public override Type BaseCLRType { get { return typeof(GeneralModule); } } public override Type AdaptorType { get { return typeof(Adaptor); } } } class Adaptor:GeneralModule, CrossBindingAdaptorType { //缓存这个数组来避免调用时的GC Alloc private object[] m_args = new object[1]; ILTypeInstance m_instance; AppDomain m_appdomain; public ILTypeInstance ILInstance { get { return m_instance; } } public Adaptor(AppDomain appdomain, ILTypeInstance instance) { this.m_appdomain = appdomain; this.m_instance = instance; LOG_TAG = "Apdator[" + m_instance.Type.Name + "]"; } //============================================================================== private IMethod mToString; private bool mToStringInvokeing; public override string ToString() { if (mToString == null) { mToString = m_instance.Type.GetMethod("ToString",0); } if (mToString != null && !mToStringInvokeing) { mToStringInvokeing = true; var result = m_appdomain.Invoke(mToString, m_instance) as string; mToStringInvokeing = false; return result; } else { return m_instance.Type.FullName; } } //============================================================================== private IMethod m_miCreate; private bool m_isCreateInvoking; public override void Create(object args = null) { //Debuger.Log(args); if (m_miCreate == null) { m_miCreate = m_instance.Type.GetMethod("Create", 1); } if (m_miCreate != null && !m_isCreateInvoking) { m_isCreateInvoking = true; m_args[0] = args; m_appdomain.Invoke(m_miCreate, m_instance, m_args); m_isCreateInvoking = false; } else { base.Create(args); } } private IMethod m_miRelease; private bool m_isReleaseInvoking; public override void Release() { //Debuger.Log(); if (m_miRelease == null) { m_miRelease = m_instance.Type.GetMethod("Release", 0); } if (m_miRelease != null && !m_isReleaseInvoking) { m_isReleaseInvoking = true; m_appdomain.Invoke(m_miRelease, m_instance); m_isReleaseInvoking = false; } else { base.Release(); } } private IMethod m_miOnHandleMessage; private bool m_isOnHandleMessageInvoking; protected override void OnModuleMessage(string msg, object[] args) { //Debuger.Log("msg:{0}, args:{1}", msg, args.ToListString()); IMethod mi = m_instance.Type.GetMethod(msg, args.Length); if (mi != null) { m_appdomain.Invoke(mi, m_instance, args); } else { if (m_miOnHandleMessage == null) { m_miOnHandleMessage = m_instance.Type.GetMethod("OnModuleMessage", 1); } if (m_miOnHandleMessage != null && !m_isOnHandleMessageInvoking) { m_isOnHandleMessageInvoking = true; m_appdomain.Invoke(m_miOnHandleMessage, m_instance, args); m_isOnHandleMessageInvoking = false; } else { base.OnModuleMessage(msg, args); } } } private IMethod m_miShow; private bool m_isShowInvoking; protected override void Show(object arg) { //Debuger.Log(arg); if (m_miShow == null) { m_miShow = m_instance.Type.GetMethod("Show", 1); } if (m_miShow != null && !m_isShowInvoking) { m_isShowInvoking = true; m_args[0] = arg; m_appdomain.Invoke(m_miShow, m_instance, m_args); m_isShowInvoking = false; } else { base.Show(arg); } } } } ================================================ FILE: SGFUnity/ILR/ModuleILR/ILRModuleActivator.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using SGF.Module; namespace SGF.Unity.ILR.ModuleILR { public class ILRModuleActivator:IModuleActivator { private string m_namespace; private string m_assemblyName; public ILRModuleActivator(string _namespace, string assemblyName) { m_namespace = _namespace; m_assemblyName = assemblyName; } public GeneralModule CreateInstance(string moduleName) { Type type = null; string fullname = m_namespace + "." + moduleName; return ILRManager.CreateInstance(fullname, m_assemblyName) as GeneralModule; } } } ================================================ FILE: SGFUnity/ILR/UIILR/ILRUILoading.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using SGF.Unity.UI; namespace SGF.Unity.ILR.UIILR { public class ILRUILoading:ILRUIPanel { } public class ILRUILoadingBridge : UILoading { public string AssemblyName = ""; public string Namespace = ""; public string TypeName = ""; private ILRUIPanel m_impl; protected override void OnAwake() { base.OnAwake(); string fullName = Namespace + "." + TypeName; m_impl = ILRManager.CreateInstance(fullName, AssemblyName) as ILRUIPanel; if (m_impl == null) { Debuger.LogError("无法在Assembly[{0}]中创建实例:{1}", AssemblyName, fullName); } else { m_impl.OnAwakeInternal(this); } } protected override void OnDestroy() { base.OnDestroy(); if (m_impl != null) { m_impl.OnDestroyInternal(); } } protected override void OnEnable() { base.OnEnable(); if (m_impl != null) { m_impl.OnEnableInternal(); } } protected override void OnDisable() { base.OnDisable(); if (m_impl != null) { m_impl.OnDisableInternal(); } } protected override void OnOpen(object arg = null) { base.OnOpen(arg); if (m_impl != null) { m_impl.OnOpenInternal(arg); } } protected override void OnClose(object arg = null) { base.OnClose(arg); if (m_impl != null) { m_impl.OnCloseInternal(arg); } } } } ================================================ FILE: SGFUnity/ILR/UIILR/ILRUILoadingAdaptor.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; using AppDomain = ILRuntime.Runtime.Enviorment.AppDomain; namespace SGF.Unity.ILR.UIILR { public class ILRUILoadingAdaptor : CrossBindingAdaptor { public override Type BaseCLRType { get { return typeof(ILRUILoading); } } public override Type AdaptorType { get { return typeof(Adaptor); } } public override object CreateCLRInstance(AppDomain appdomain, ILTypeInstance instance) { return new Adaptor(appdomain, instance); //创建一个新的实例 } class Adaptor : ILRUIPanelAdaptor.Adaptor { private ILTypeInstance m_instance; private AppDomain m_appdomain; private object[] m_args = new object[1]; public Adaptor(AppDomain appdomain, ILTypeInstance instance) : base(appdomain, instance) { this.m_appdomain = appdomain; this.m_instance = instance; } //============================================================================== } } } ================================================ FILE: SGFUnity/ILR/UIILR/ILRUIPage.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using SGF.Unity.UI; namespace SGF.Unity.ILR.UIILR { public class ILRUIPage:ILRUIPanel { } public class ILRUIPageBridge : UIPage { public string AssemblyName = ""; public string Namespace = ""; public string TypeName = ""; private ILRUIPanel m_impl; protected override void OnAwake() { base.OnAwake(); string fullName = Namespace + "." + TypeName; m_impl = ILRManager.CreateInstance(fullName, AssemblyName) as ILRUIPanel; if (m_impl == null) { Debuger.LogError("无法在Assembly[{0}]中创建实例:{1}", AssemblyName, fullName); } else { m_impl.OnAwakeInternal(this); } } protected override void OnDestroy() { base.OnDestroy(); if (m_impl != null) { m_impl.OnDestroyInternal(); } } protected override void OnEnable() { base.OnEnable(); if (m_impl != null) { m_impl.OnEnableInternal(); } } protected override void OnDisable() { base.OnDisable(); if (m_impl != null) { m_impl.OnDisableInternal(); } } protected override void OnOpen(object arg = null) { base.OnOpen(arg); if (m_impl != null) { m_impl.OnOpenInternal(arg); } } protected override void OnClose(object arg = null) { base.OnClose(arg); if (m_impl != null) { m_impl.OnCloseInternal(arg); } } } } ================================================ FILE: SGFUnity/ILR/UIILR/ILRUIPageAdaptor.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; using AppDomain = ILRuntime.Runtime.Enviorment.AppDomain; namespace SGF.Unity.ILR.UIILR { public class ILRUIPageAdaptor : CrossBindingAdaptor { public override Type BaseCLRType { get { return typeof(ILRUIPage); } } public override Type AdaptorType { get { return typeof(Adaptor); } } public override object CreateCLRInstance(AppDomain appdomain, ILTypeInstance instance) { return new Adaptor(appdomain, instance); //创建一个新的实例 } class Adaptor : ILRUIPanelAdaptor.Adaptor { private ILTypeInstance m_instance; private AppDomain m_appdomain; private object[] m_args = new object[1]; public Adaptor(AppDomain appdomain, ILTypeInstance instance) :base(appdomain, instance) { this.m_appdomain = appdomain; this.m_instance = instance; } //============================================================================== } } } ================================================ FILE: SGFUnity/ILR/UIILR/ILRUIPanel.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using SGF.Unity.UI; namespace SGF.Unity.ILR.UIILR { public class ILRUIPanel { private UIPanel m_base; public UIPanel Base{get { return m_base; }} protected virtual void OnAwake() { } internal void OnAwakeInternal(UIPanel _base) { m_base = _base; OnAwake(); } protected virtual void OnDestroy() { } internal void OnDestroyInternal() { OnDestroy(); } protected virtual void OnOpen(object arg = null) { } internal void OnOpenInternal(object arg) { OnOpen(arg); } protected virtual void OnClose(object arg = null) { } internal void OnCloseInternal(object arg) { OnClose(arg); } protected virtual void OnEnable() { } internal void OnEnableInternal() { OnEnable(); } protected virtual void OnDisable() { } internal void OnDisableInternal() { OnDisable(); } } public class ILRUIPanelBridge : UIPanel { public string AssemblyName = ""; public string Namespace = ""; public string TypeName = ""; private ILRUIPanel m_impl; protected override void OnAwake() { base.OnAwake(); string fullName = Namespace + "." + TypeName; m_impl = ILRManager.CreateInstance(fullName, AssemblyName) as ILRUIPanel; if (m_impl == null) { Debuger.LogError("无法在Assembly[{0}]中创建实例:{1}", AssemblyName, fullName); } else { m_impl.OnAwakeInternal(this); } } protected override void OnDestroy() { base.OnDestroy(); if (m_impl != null) { m_impl.OnDestroyInternal(); } } protected override void OnEnable() { base.OnEnable(); if (m_impl != null) { m_impl.OnEnableInternal(); } } protected override void OnDisable() { base.OnDisable(); if (m_impl != null) { m_impl.OnDisableInternal(); } } protected override void OnOpen(object arg = null) { base.OnOpen(arg); if (m_impl != null) { m_impl.OnOpenInternal(arg); } } protected override void OnClose(object arg = null) { base.OnClose(arg); if (m_impl != null) { m_impl.OnCloseInternal(arg); } } } } ================================================ FILE: SGFUnity/ILR/UIILR/ILRUIPanelAdaptor.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; using AppDomain = ILRuntime.Runtime.Enviorment.AppDomain; namespace SGF.Unity.ILR.UIILR { public class ILRUIPanelAdaptor : CrossBindingAdaptor { public override Type BaseCLRType { get { return typeof(ILRUIPanel); } } public override Type AdaptorType { get { return typeof(Adaptor); } } public override object CreateCLRInstance(AppDomain appdomain, ILTypeInstance instance) { return new Adaptor(appdomain, instance); //创建一个新的实例 } internal class Adaptor : ILRUIPage, CrossBindingAdaptorType { ILTypeInstance m_instance; AppDomain m_appdomain; public ILTypeInstance ILInstance { get { return m_instance; } } //缓存这个数组来避免调用时的GC Alloc private object[] m_args = new object[1]; public Adaptor(AppDomain appdomain, ILTypeInstance instance) { this.m_appdomain = appdomain; this.m_instance = instance; } //============================================================================== private IMethod mToString; private bool mToStringInvokeing; public override string ToString() { if (mToString == null) { mToString = m_instance.Type.GetMethod("ToString", 0); } if (mToString != null && !mToStringInvokeing) { mToStringInvokeing = true; var result = m_appdomain.Invoke(mToString, m_instance) as string; mToStringInvokeing = false; return result; } else { return m_instance.Type.FullName; } } //============================================================================== private IMethod m_miOnAwake; private bool m_isOnAwakeInvoking; protected override void OnAwake() { if (m_miOnAwake == null) { m_miOnAwake = m_instance.Type.GetMethod("OnAwake", 0); } if (m_miOnAwake != null && !m_isOnOpenInvoking) { m_isOnAwakeInvoking = true; m_appdomain.Invoke(m_miOnAwake, m_instance); m_isOnAwakeInvoking = false; } else { base.OnAwake(); } } //============================================================================== private IMethod m_miOnOpen; private bool m_isOnOpenInvoking; protected override void OnOpen(object args = null) { Debuger.Log(args); if (m_miOnOpen == null) { m_miOnOpen = m_instance.Type.GetMethod("OnOpen", 1); } if (m_miOnOpen != null && !m_isOnOpenInvoking) { m_isOnOpenInvoking = true; m_args[0] = args; m_appdomain.Invoke(m_miOnOpen, m_instance, m_args); m_isOnOpenInvoking = false; } else { base.OnOpen(args); } } //============================================================================== private IMethod m_miOnClose; private bool m_isOnCloseInvoking; protected override void OnClose(object args = null) { Debuger.Log(args); if (m_miOnClose == null) { m_miOnClose = m_instance.Type.GetMethod("OnClose", 1); } if (m_miOnClose != null && !m_isOnCloseInvoking) { m_isOnCloseInvoking = true; m_args[0] = args; m_appdomain.Invoke(m_miOnClose, m_instance, m_args); m_isOnCloseInvoking = false; } else { base.OnClose(args); } } //============================================================================== } } } ================================================ FILE: SGFUnity/ILR/UIILR/ILRUIWidget.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using SGF.Unity.UI; namespace SGF.Unity.ILR.UIILR { public class ILRUIWidget:ILRUIPanel { } public class ILRUIWidgetBridge : UIWidget { public string AssemblyName = ""; public string Namespace = ""; public string TypeName = ""; private ILRUIPanel m_impl; protected override void OnAwake() { base.OnAwake(); string fullName = Namespace + "." + TypeName; m_impl = ILRManager.CreateInstance(fullName, AssemblyName) as ILRUIPanel; if (m_impl == null) { Debuger.LogError("无法在Assembly[{0}]中创建实例:{1}", AssemblyName, fullName); } else { m_impl.OnAwakeInternal(this); } } protected override void OnDestroy() { base.OnDestroy(); if (m_impl != null) { m_impl.OnDestroyInternal(); } } protected override void OnEnable() { base.OnEnable(); if (m_impl != null) { m_impl.OnEnableInternal(); } } protected override void OnDisable() { base.OnDisable(); if (m_impl != null) { m_impl.OnDisableInternal(); } } protected override void OnOpen(object arg = null) { base.OnOpen(arg); if (m_impl != null) { m_impl.OnOpenInternal(arg); } } protected override void OnClose(object arg = null) { base.OnClose(arg); if (m_impl != null) { m_impl.OnCloseInternal(arg); } } } } ================================================ FILE: SGFUnity/ILR/UIILR/ILRUIWidgetAdaptor.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; using AppDomain = ILRuntime.Runtime.Enviorment.AppDomain; namespace SGF.Unity.ILR.UIILR { public class ILRUIWidgetAdaptor : CrossBindingAdaptor { public override Type BaseCLRType { get { return typeof(ILRUIWidget); } } public override Type AdaptorType { get { return typeof(Adaptor); } } public override object CreateCLRInstance(AppDomain appdomain, ILTypeInstance instance) { return new Adaptor(appdomain, instance); //创建一个新的实例 } class Adaptor : ILRUIPanelAdaptor.Adaptor { private ILTypeInstance m_instance; private AppDomain m_appdomain; private object[] m_args = new object[1]; public Adaptor(AppDomain appdomain, ILTypeInstance instance) : base(appdomain, instance) { this.m_appdomain = appdomain; this.m_instance = instance; } //============================================================================== } } } ================================================ FILE: SGFUnity/ILR/UIILR/ILRUIWindow.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using SGF.Unity.UI; namespace SGF.Unity.ILR.UIILR { public class ILRUIWindow : ILRUIPanel { } public class ILRUIWindowBridge : UIWindow { public string AssemblyName = ""; public string Namespace = ""; public string TypeName = ""; private ILRUIPanel m_impl; protected override void OnAwake() { base.OnAwake(); string fullName = Namespace + "." + TypeName; m_impl = ILRManager.CreateInstance(fullName, AssemblyName) as ILRUIPanel; if (m_impl == null) { Debuger.LogError("无法在Assembly[{0}]中创建实例:{1}", AssemblyName, fullName); } else { m_impl.OnAwakeInternal(this); } } protected override void OnDestroy() { base.OnDestroy(); if (m_impl != null) { m_impl.OnDestroyInternal(); } } protected override void OnEnable() { base.OnEnable(); if (m_impl != null) { m_impl.OnEnableInternal(); } } protected override void OnDisable() { base.OnDisable(); if (m_impl != null) { m_impl.OnDisableInternal(); } } protected override void OnOpen(object arg = null) { base.OnOpen(arg); if (m_impl != null) { m_impl.OnOpenInternal(arg); } } protected override void OnClose(object arg = null) { base.OnClose(arg); if (m_impl != null) { m_impl.OnCloseInternal(arg); } } } } ================================================ FILE: SGFUnity/ILR/UIILR/ILRUIWindowAdaptor.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; using AppDomain = ILRuntime.Runtime.Enviorment.AppDomain; namespace SGF.Unity.ILR.UIILR { public class ILRUIWindowAdaptor : CrossBindingAdaptor { public override Type BaseCLRType { get { return typeof(ILRUIWindow); } } public override Type AdaptorType { get { return typeof(Adaptor); } } public override object CreateCLRInstance(AppDomain appdomain, ILTypeInstance instance) { return new Adaptor(appdomain, instance); //创建一个新的实例 } class Adaptor : ILRUIPanelAdaptor.Adaptor { private ILTypeInstance m_instance; private AppDomain m_appdomain; private object[] m_args = new object[1]; public Adaptor(AppDomain appdomain, ILTypeInstance instance) : base(appdomain, instance) { this.m_appdomain = appdomain; this.m_instance = instance; } //============================================================================== } } } ================================================ FILE: SGFUnity/ILRuntime/Adapters/Editor/ILRuntimeCLRBinding.cs ================================================ #if UNITY_EDITOR using UnityEditor; using UnityEngine; using System; using System.Text; using System.Collections.Generic; using OT.Foundation; [System.Reflection.Obfuscation(Exclude = true)] public class ILRuntimeCLRBinding { [MenuItem("ILRuntime/Generate CLR Binding Code")] static void GenerateCLRBinding() { List types = new List(); types.Add(typeof(int)); types.Add(typeof(float)); types.Add(typeof(long)); types.Add(typeof(object)); types.Add(typeof(string)); types.Add(typeof(Array)); types.Add(typeof(Vector2)); types.Add(typeof(Vector3)); types.Add(typeof(Quaternion)); types.Add(typeof(GameObject)); types.Add(typeof(UnityEngine.Object)); types.Add(typeof(Transform)); types.Add(typeof(RectTransform)); types.Add(typeof(CLRBindingTestClass)); types.Add(typeof(Time)); types.Add(typeof(Debug)); types.Add(typeof(OT.Foundation.Debuger)); //所有DLL内的类型的真实C#类型都是ILTypeInstance types.Add(typeof(List)); ILRuntime.Runtime.CLRBinding.BindingCodeGenerator.GenerateBindingCode(types, "Assets/ILRuntime/Generated"); } [MenuItem("ILRuntime/Generate CLR Binding Code by Analysis")] static void GenerateCLRBindingByAnalysis() { //用新的分析热更dll调用引用来生成绑定代码 ILRuntime.Runtime.Enviorment.AppDomain domain = new ILRuntime.Runtime.Enviorment.AppDomain(); using (System.IO.FileStream fs = new System.IO.FileStream("Assets/StreamingAssets/HotFix_Project.dll", System.IO.FileMode.Open, System.IO.FileAccess.Read)) { domain.LoadAssembly(fs); } //Crossbind Adapter is needed to generate the correct binding code InitILRuntime(domain); ILRuntime.Runtime.CLRBinding.BindingCodeGenerator.GenerateBindingCode(domain, "Assets/ILRuntime/Generated"); } static void InitILRuntime(ILRuntime.Runtime.Enviorment.AppDomain domain) { //这里需要注册所有热更DLL中用到的跨域继承Adapter,否则无法正确抓取引用 domain.RegisterCrossBindingAdaptor(new MonoBehaviourAdapter()); domain.RegisterCrossBindingAdaptor(new CoroutineAdapter()); domain.RegisterCrossBindingAdaptor(new InheritanceAdapter()); } } #endif ================================================ FILE: SGFUnity/ILRuntime/CLR/Method/CLRMethod.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using Mono.Cecil; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Enviorment; using ILRuntime.CLR.TypeSystem; using ILRuntime.Runtime.Stack; using ILRuntime.CLR.Utils; namespace ILRuntime.CLR.Method { public class CLRMethod : IMethod { MethodInfo def; ConstructorInfo cDef; List parameters; ILRuntime.Runtime.Enviorment.AppDomain appdomain; CLRType declaringType; ParameterInfo[] param; bool isConstructor; CLRRedirectionDelegate redirect; IType[] genericArguments; object[] invocationParam; bool isDelegateInvoke; int hashCode = -1; static int instance_id = 0x20000000; public IType DeclearingType { get { return declaringType; } } public string Name { get { return def.Name; } } public bool HasThis { get { return isConstructor ? !cDef.IsStatic : !def.IsStatic; } } public int GenericParameterCount { get { if (def.ContainsGenericParameters && def.IsGenericMethodDefinition) { return def.GetGenericArguments().Length; } return 0; } } public bool IsGenericInstance { get { return genericArguments != null; } } public bool IsDelegateInvoke { get { return isDelegateInvoke; } } public bool IsStatic { get { return def.IsStatic; } } public CLRRedirectionDelegate Redirection { get { return redirect; } } public MethodInfo MethodInfo { get { return def; } } public ConstructorInfo ConstructorInfo { get { return cDef; } } public IType[] GenericArguments { get { return genericArguments; } } internal CLRMethod(MethodInfo def, CLRType type, ILRuntime.Runtime.Enviorment.AppDomain domain) { this.def = def; declaringType = type; this.appdomain = domain; param = def.GetParameters(); if (!def.ContainsGenericParameters) { ReturnType = domain.GetType(def.ReturnType.FullName); if (ReturnType == null) { ReturnType = domain.GetType(def.ReturnType.AssemblyQualifiedName); } } if (type.IsDelegate && def.Name == "Invoke") isDelegateInvoke = true; isConstructor = false; if (def != null) { if (def.IsGenericMethod && !def.IsGenericMethodDefinition) { appdomain.RedirectMap.TryGetValue(def.GetGenericMethodDefinition(), out redirect); } else appdomain.RedirectMap.TryGetValue(def, out redirect); } } internal CLRMethod(ConstructorInfo def, CLRType type, ILRuntime.Runtime.Enviorment.AppDomain domain) { this.cDef = def; declaringType = type; this.appdomain = domain; param = def.GetParameters(); if (!def.ContainsGenericParameters) { ReturnType = type; } isConstructor = true; if (def != null) { appdomain.RedirectMap.TryGetValue(cDef, out redirect); } } public int ParameterCount { get { return param != null ? param.Length : 0; } } public List Parameters { get { if (parameters == null) { InitParameters(); } return parameters; } } public IType ReturnType { get; private set; } public bool IsConstructor { get { return cDef != null; } } void InitParameters() { parameters = new List(); foreach (var i in param) { IType type = appdomain.GetType(i.ParameterType.FullName); if (type == null) type = appdomain.GetType(i.ParameterType.AssemblyQualifiedName); if (i.ParameterType.IsGenericTypeDefinition) { if (type == null) type = appdomain.GetType(i.ParameterType.GetGenericTypeDefinition().FullName); if (type == null) type = appdomain.GetType(i.ParameterType.GetGenericTypeDefinition().AssemblyQualifiedName); } if (i.ParameterType.ContainsGenericParameters) { var t = i.ParameterType; if (t.HasElementType) t = i.ParameterType.GetElementType(); else if (t.GetGenericArguments().Length > 0) { t = t.GetGenericArguments()[0]; } type = new ILGenericParameterType(t.Name); } if (type == null) throw new TypeLoadException(); parameters.Add(type); } } unsafe StackObject* Minus(StackObject* a, int b) { return (StackObject*)((long)a - sizeof(StackObject) * b); } public unsafe object Invoke(Runtime.Intepreter.ILIntepreter intepreter, StackObject* esp, IList mStack, bool isNewObj = false) { if (parameters == null) { InitParameters(); } int paramCount = ParameterCount; if (invocationParam == null) invocationParam = new object[paramCount]; object[] param = invocationParam; for (int i = paramCount; i >= 1; i--) { var p = Minus(esp, i); var obj = this.param[paramCount - i].ParameterType.CheckCLRTypes(StackObject.ToObject(p, appdomain, mStack)); obj = ILIntepreter.CheckAndCloneValueType(obj, appdomain); param[paramCount - i] = obj; } if (isConstructor) { if (!isNewObj) { if (!cDef.IsStatic) { object instance = declaringType.TypeForCLR.CheckCLRTypes(StackObject.ToObject((Minus(esp, paramCount + 1)), appdomain, mStack)); if (instance == null) throw new NullReferenceException(); if (instance is CrossBindingAdaptorType && paramCount == 0)//It makes no sense to call the Adaptor's default constructor return null; cDef.Invoke(instance, param); return null; } else { throw new NotImplementedException(); } } else { var res = cDef.Invoke(param); FixReference(paramCount, esp, param, mStack); return res; } } else { object instance = null; if (!def.IsStatic) { instance = declaringType.TypeForCLR.CheckCLRTypes(StackObject.ToObject((Minus(esp, paramCount + 1)), appdomain, mStack)); if (instance == null) throw new NullReferenceException(); } object res = null; /*if (redirect != null) res = redirect(new ILContext(appdomain, intepreter, esp, mStack, this), instance, param, genericArguments); else*/ { res = def.Invoke(instance, param); } FixReference(paramCount, esp, param, mStack); return res; } } unsafe void FixReference(int paramCount, StackObject* esp, object[] param, IList mStack) { for (int i = paramCount; i >= 1; i--) { var p = Minus(esp, i); var val = param[paramCount - i]; switch (p->ObjectType) { case ObjectTypes.StackObjectReference: { var dst = *(StackObject**)&p->Value; if (dst->ObjectType >= ObjectTypes.Object) { var obj = val; if (obj is CrossBindingAdaptorType) obj = ((CrossBindingAdaptorType)obj).ILInstance; mStack[dst->Value] = obj; } else { ILIntepreter.UnboxObject(dst, val); } } break; case ObjectTypes.FieldReference: { var obj = mStack[p->Value]; if(obj is ILTypeInstance) { ((ILTypeInstance)obj)[p->ValueLow] = val; } else { var t = appdomain.GetType(obj.GetType()) as CLRType; t.GetField(p->ValueLow).SetValue(obj, val); } } break; case ObjectTypes.StaticFieldReference: { var t = appdomain.GetType(p->Value); if(t is ILType) { ((ILType)t).StaticInstance[p->ValueLow] = val; } else { ((CLRType)t).SetStaticFieldValue(p->ValueLow, val); } } break; } } } public IMethod MakeGenericMethod(IType[] genericArguments) { Type[] p = new Type[genericArguments.Length]; for (int i = 0; i < genericArguments.Length; i++) { p[i] = genericArguments[i].TypeForCLR; } var t = def.MakeGenericMethod(p); var res = new CLRMethod(t, declaringType, appdomain); res.genericArguments = genericArguments; return res; } public override string ToString() { if (def != null) return def.ToString(); else return cDef.ToString(); } public override int GetHashCode() { if (hashCode == -1) hashCode = System.Threading.Interlocked.Add(ref instance_id, 1); return hashCode; } } } ================================================ FILE: SGFUnity/ILRuntime/CLR/Method/ExceptionHandler.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.TypeSystem; namespace ILRuntime.CLR.Method { enum ExceptionHandlerType { Catch, Finally, Fault, } class ExceptionHandler { public ExceptionHandlerType HandlerType { get; set; } public int TryStart { get; set; } public int TryEnd { get; set; } public int HandlerStart { get; set; } public int HandlerEnd { get; set; } public IType CatchType { get; set; } } } ================================================ FILE: SGFUnity/ILRuntime/CLR/Method/ILMethod.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using Mono.Cecil; using ILRuntime.Runtime.Intepreter.OpCodes; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Debugger; using ILRuntime.CLR.TypeSystem; using ILRuntime.Reflection; namespace ILRuntime.CLR.Method { public class ILMethod : IMethod { OpCode[] body; MethodDefinition def; List parameters; ILRuntime.Runtime.Enviorment.AppDomain appdomain; ILType declaringType; ExceptionHandler[] exceptionHandler; KeyValuePair[] genericParameters; IType[] genericArguments; Dictionary jumptables; bool isDelegateInvoke; ILRuntimeMethodInfo refletionMethodInfo; ILRuntimeConstructorInfo reflectionCtorInfo; int paramCnt, localVarCnt; Mono.Collections.Generic.Collection variables; int hashCode = -1; static int instance_id = 0x10000000; public MethodDefinition Definition { get { return def; } } public Dictionary JumpTables { get { return jumptables; } } internal IDelegateAdapter DelegateAdapter { get; set; } internal int StartLine { get; set; } internal int EndLine { get; set; } public MethodInfo ReflectionMethodInfo { get { if (IsConstructor) throw new NotSupportedException(); if (refletionMethodInfo == null) refletionMethodInfo = new ILRuntimeMethodInfo(this); return refletionMethodInfo; } } public ConstructorInfo ReflectionConstructorInfo { get { if (!IsConstructor) throw new NotSupportedException(); if (reflectionCtorInfo == null) reflectionCtorInfo = new ILRuntimeConstructorInfo(this); return reflectionCtorInfo; } } internal ExceptionHandler[] ExceptionHandler { get { if (body == null) InitCodeBody(); return exceptionHandler; } } public string Name { get { return def.Name; } } public IType DeclearingType { get { return declaringType; } } public bool HasThis { get { return def.HasThis; } } public int GenericParameterCount { get { if (IsGenericInstance) return 0; return def.GenericParameters.Count; } } public bool IsGenericInstance { get { return genericParameters != null; } } public Mono.Collections.Generic.Collection Variables { get { return variables; } } public KeyValuePair[] GenericArguments { get { return genericParameters; } } public IType[] GenericArugmentsArray { get { return genericArguments; } } public ILMethod(MethodDefinition def, ILType type, ILRuntime.Runtime.Enviorment.AppDomain domain) { this.def = def; declaringType = type; if (def.ReturnType.IsGenericParameter) { ReturnType = FindGenericArgument(def.ReturnType.Name); } else ReturnType = domain.GetType(def.ReturnType, type, this); if (type.IsDelegate && def.Name == "Invoke") isDelegateInvoke = true; this.appdomain = domain; paramCnt = def.HasParameters ? def.Parameters.Count : 0; #if DEBUG if (def.HasBody) { var sp = DebugService.FindSequencePoint(def.Body.Instructions[0]); if (sp != null) { StartLine = sp.StartLine; sp = DebugService.FindSequencePoint(def.Body.Instructions[def.Body.Instructions.Count - 1]); if (sp != null) { EndLine = sp.EndLine; } } } #endif } public IType FindGenericArgument(string name) { IType res = declaringType.FindGenericArgument(name); if (res == null && genericParameters != null) { foreach (var i in genericParameters) { if (i.Key == name) return i.Value; } } else return res; return null; } internal OpCode[] Body { get { if (body == null) InitCodeBody(); return body; } } public int LocalVariableCount { get { return localVarCnt; } } public bool IsConstructor { get { return def.IsConstructor; } } public bool IsDelegateInvoke { get { return isDelegateInvoke; } } public bool IsStatic { get { return def.IsStatic; } } public int ParameterCount { get { return paramCnt; } } public List Parameters { get { if (def.HasParameters && parameters == null) { InitParameters(); } return parameters; } } public IType ReturnType { get; private set; } void InitCodeBody() { if (def.HasBody) { localVarCnt = def.Body.Variables.Count; body = new OpCode[def.Body.Instructions.Count]; Dictionary addr = new Dictionary(); for (int i = 0; i < body.Length; i++) { var c = def.Body.Instructions[i]; OpCode code = new OpCode(); code.Code = (OpCodeEnum)c.OpCode.Code; addr[c] = i; body[i] = code; } for (int i = 0; i < body.Length; i++) { var c = def.Body.Instructions[i]; InitToken(ref body[i], c.Operand, addr); } for (int i = 0; i < def.Body.ExceptionHandlers.Count; i++) { var eh = def.Body.ExceptionHandlers[i]; if (exceptionHandler == null) exceptionHandler = new Method.ExceptionHandler[def.Body.ExceptionHandlers.Count]; ExceptionHandler e = new ExceptionHandler(); e.HandlerStart = addr[eh.HandlerStart]; e.HandlerEnd = addr[eh.HandlerEnd] - 1; e.TryStart = addr[eh.TryStart]; e.TryEnd = addr[eh.TryEnd] - 1; switch (eh.HandlerType) { case Mono.Cecil.Cil.ExceptionHandlerType.Catch: e.CatchType = appdomain.GetType(eh.CatchType, declaringType, this); e.HandlerType = ExceptionHandlerType.Catch; break; case Mono.Cecil.Cil.ExceptionHandlerType.Finally: e.HandlerType = ExceptionHandlerType.Finally; break; case Mono.Cecil.Cil.ExceptionHandlerType.Fault: e.HandlerType = ExceptionHandlerType.Fault; break; default: throw new NotImplementedException(); } exceptionHandler[i] = e; //Mono.Cecil.Cil.ExceptionHandlerType. } //Release Method body to save memory variables = def.Body.Variables; def.Body = null; } else body = new OpCode[0]; } unsafe void InitToken(ref OpCode code, object token, Dictionary addr) { switch (code.Code) { case OpCodeEnum.Leave: case OpCodeEnum.Leave_S: case OpCodeEnum.Br: case OpCodeEnum.Br_S: case OpCodeEnum.Brtrue: case OpCodeEnum.Brtrue_S: case OpCodeEnum.Brfalse: case OpCodeEnum.Brfalse_S: //比较流程控制 case OpCodeEnum.Beq: case OpCodeEnum.Beq_S: case OpCodeEnum.Bne_Un: case OpCodeEnum.Bne_Un_S: case OpCodeEnum.Bge: case OpCodeEnum.Bge_S: case OpCodeEnum.Bge_Un: case OpCodeEnum.Bge_Un_S: case OpCodeEnum.Bgt: case OpCodeEnum.Bgt_S: case OpCodeEnum.Bgt_Un: case OpCodeEnum.Bgt_Un_S: case OpCodeEnum.Ble: case OpCodeEnum.Ble_S: case OpCodeEnum.Ble_Un: case OpCodeEnum.Ble_Un_S: case OpCodeEnum.Blt: case OpCodeEnum.Blt_S: case OpCodeEnum.Blt_Un: case OpCodeEnum.Blt_Un_S: code.TokenInteger = addr[(Mono.Cecil.Cil.Instruction)token]; break; case OpCodeEnum.Ldc_I4: code.TokenInteger = (int)token; break; case OpCodeEnum.Ldc_I4_S: code.TokenInteger = (sbyte)token; break; case OpCodeEnum.Ldc_I8: code.TokenLong = (long)token; break; case OpCodeEnum.Ldc_R4: { float val = (float)token; code.TokenInteger = *(int*)&val; } break; case OpCodeEnum.Ldc_R8: { double val = (double)token; code.TokenLong = *(long*)&val; } break; case OpCodeEnum.Stloc: case OpCodeEnum.Stloc_S: case OpCodeEnum.Ldloc: case OpCodeEnum.Ldloc_S: case OpCodeEnum.Ldloca: case OpCodeEnum.Ldloca_S: { Mono.Cecil.Cil.VariableDefinition vd = (Mono.Cecil.Cil.VariableDefinition)token; code.TokenInteger = vd.Index; } break; case OpCodeEnum.Ldarg_S: case OpCodeEnum.Ldarg: case OpCodeEnum.Ldarga: case OpCodeEnum.Ldarga_S: case OpCodeEnum.Starg: case OpCodeEnum.Starg_S: { Mono.Cecil.ParameterDefinition vd = (Mono.Cecil.ParameterDefinition)token; code.TokenInteger = vd.Index; if (HasThis) code.TokenInteger++; } break; case OpCodeEnum.Call: case OpCodeEnum.Newobj: case OpCodeEnum.Ldftn: case OpCodeEnum.Ldvirtftn: case OpCodeEnum.Callvirt: { bool invalidToken; var m = appdomain.GetMethod(token, declaringType, this, out invalidToken); if (m != null) { if (invalidToken) code.TokenInteger = m.GetHashCode(); else code.TokenInteger = token.GetHashCode(); } else { //Cannot find method or the method is dummy MethodReference _ref = (MethodReference)token; int paramCnt = _ref.HasParameters ? _ref.Parameters.Count : 0; if (_ref.HasThis) paramCnt++; code.TokenLong = paramCnt; } } break; case OpCodeEnum.Constrained: case OpCodeEnum.Box: case OpCodeEnum.Unbox_Any: case OpCodeEnum.Unbox: case OpCodeEnum.Initobj: case OpCodeEnum.Isinst: case OpCodeEnum.Newarr: case OpCodeEnum.Stobj: case OpCodeEnum.Ldobj: { code.TokenInteger = GetTypeTokenHashCode(token); } break; case OpCodeEnum.Stfld: case OpCodeEnum.Ldfld: case OpCodeEnum.Ldflda: { code.TokenLong = appdomain.GetStaticFieldIndex(token, declaringType, this); } break; case OpCodeEnum.Stsfld: case OpCodeEnum.Ldsfld: case OpCodeEnum.Ldsflda: { code.TokenLong = appdomain.GetStaticFieldIndex(token, declaringType, this); } break; case OpCodeEnum.Ldstr: { long hashCode = appdomain.CacheString(token); code.TokenLong = hashCode; } break; case OpCodeEnum.Ldtoken: { if (token is FieldReference) { code.TokenInteger = 0; code.TokenLong = appdomain.GetStaticFieldIndex(token, declaringType, this); } else if (token is TypeReference) { code.TokenInteger = 1; code.TokenLong = GetTypeTokenHashCode(token); } else throw new NotImplementedException(); } break; case OpCodeEnum.Switch: { PrepareJumpTable(token, addr); code.TokenInteger = token.GetHashCode(); } break; } } int GetTypeTokenHashCode(object token) { var t = appdomain.GetType(token, declaringType, this); bool isGenericParameter = CheckHasGenericParamter(token); if (t == null && isGenericParameter) { t = FindGenericArgument(((TypeReference)token).Name); } if (t != null) { if (t is ILType) { if (((ILType)t).TypeReference.HasGenericParameters) return t.GetHashCode(); else return ((ILType)t).TypeReference.GetHashCode(); } else if (isGenericParameter) { return t.GetHashCode(); } else return token.GetHashCode(); } return 0; } bool CheckHasGenericParamter(object token) { if (token is TypeReference) { TypeReference _ref = ((TypeReference)token); if (_ref.IsGenericParameter) return true; if (_ref.IsGenericInstance) { GenericInstanceType gi = (GenericInstanceType)_ref; foreach(var i in gi.GenericArguments) { if (CheckHasGenericParamter(i)) return true; } return false; } else return false; } else return false; } void PrepareJumpTable(object token, Dictionary addr) { int hashCode = token.GetHashCode(); if (jumptables == null) jumptables = new Dictionary(); if (jumptables.ContainsKey(hashCode)) return; Mono.Cecil.Cil.Instruction[] e = token as Mono.Cecil.Cil.Instruction[]; int[] addrs = new int[e.Length]; for (int i = 0; i < e.Length; i++) { addrs[i] = addr[e[i]]; } jumptables[hashCode] = addrs; } void InitParameters() { parameters = new List(); foreach (var i in def.Parameters) { IType type = null; bool isByRef = false; bool isArray = false; TypeReference pt = i.ParameterType; if (i.ParameterType.IsByReference) { isByRef = true; pt = pt.GetElementType(); } if (i.ParameterType.IsArray) { isArray = true; pt = pt.GetElementType(); } if (pt.IsGenericParameter) { type = FindGenericArgument(pt.Name); if (type == null && def.HasGenericParameters) { bool found = false; foreach (var j in def.GenericParameters) { if (j.Name == pt.Name) { found = true; break; } } if (found) { type = new ILGenericParameterType(pt.Name); } else throw new NotSupportedException("Cannot find Generic Parameter " + pt.Name + " in " + def.FullName); } if (isByRef) type = type.MakeByRefType(); if (isArray) type = type.MakeArrayType(); } else type = appdomain.GetType(i.ParameterType, declaringType, this); parameters.Add(type); } } public IMethod MakeGenericMethod(IType[] genericArguments) { KeyValuePair[] genericParameters = new KeyValuePair[genericArguments.Length]; for (int i = 0; i < genericArguments.Length; i++) { string name = def.GenericParameters[i].Name; IType val = genericArguments[i]; genericParameters[i] = new KeyValuePair(name, val); } ILMethod m = new ILMethod(def, declaringType, appdomain); m.genericParameters = genericParameters; m.genericArguments = genericArguments; if (m.def.ReturnType.IsGenericParameter) { m.ReturnType = m.FindGenericArgument(m.def.ReturnType.Name); } return m; } public override string ToString() { StringBuilder sb = new StringBuilder(); sb.Append(declaringType.FullName); sb.Append('.'); sb.Append(Name); sb.Append('('); bool isFirst = true; if (parameters == null) InitParameters(); for (int i = 0; i < parameters.Count; i++) { if (isFirst) isFirst = false; else sb.Append(", "); sb.Append(parameters[i].Name); sb.Append(' '); sb.Append(def.Parameters[i].Name); } sb.Append(')'); return sb.ToString(); } public override int GetHashCode() { if (hashCode == -1) hashCode = System.Threading.Interlocked.Add(ref instance_id, 1); return hashCode; } } } ================================================ FILE: SGFUnity/ILRuntime/CLR/Method/IMethod.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.TypeSystem; namespace ILRuntime.CLR.Method { public interface IMethod { string Name { get; } int ParameterCount { get; } bool HasThis { get; } IType DeclearingType { get; } IType ReturnType { get; } List Parameters { get; } int GenericParameterCount { get; } bool IsGenericInstance { get; } bool IsConstructor { get; } bool IsDelegateInvoke { get; } bool IsStatic { get; } IMethod MakeGenericMethod(IType[] genericArguments); } } ================================================ FILE: SGFUnity/ILRuntime/CLR/TypeSystem/CLRType.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using Mono.Cecil; using ILRuntime.CLR.Method; using ILRuntime.Reflection; using ILRuntime.Runtime.Enviorment; namespace ILRuntime.CLR.TypeSystem { public class CLRType : IType { Type clrType; bool isPrimitive, isValueType; Dictionary> methods; ILRuntime.Runtime.Enviorment.AppDomain appdomain; List constructors; KeyValuePair[] genericArguments; List genericInstances; Dictionary fieldMapping; Dictionary fieldInfoCache; Dictionary fieldGetterCache; Dictionary fieldSetterCache; Dictionary fieldIdxMapping; IType[] orderedFieldTypes; CLRMemberwiseCloneDelegate memberwiseCloneDelegate; CLRCreateDefaultInstanceDelegate createDefaultInstanceDelegate; CLRCreateArrayInstanceDelegate createArrayInstanceDelegate; Dictionary fieldTokenMapping; IType byRefType, arrayType, elementType; IType[] interfaces; bool isDelegate; IType baseType; bool isBaseTypeInitialized = false, interfaceInitialized = false, valueTypeBinderGot = false; ILRuntimeWrapperType wraperType; ValueTypeBinder valueTypeBinder; int hashCode = -1; static int instance_id = 0x20000000; public Dictionary Fields { get { if (fieldMapping == null) InitializeFields(); return fieldInfoCache; } } public Dictionary FieldIndexMapping { get { return fieldIdxMapping; } } public IType[] OrderedFieldTypes { get { if (fieldMapping == null) InitializeFields(); return orderedFieldTypes; } } public int TotalFieldCount { get { if (fieldMapping == null) InitializeFields(); return fieldIdxMapping.Count; } } public ILRuntime.Runtime.Enviorment.AppDomain AppDomain { get { return appdomain; } } public CLRType(Type clrType, Runtime.Enviorment.AppDomain appdomain) { this.clrType = clrType; this.appdomain = appdomain; isPrimitive = clrType.IsPrimitive; isValueType = clrType.IsValueType; isDelegate = clrType.BaseType == typeof(MulticastDelegate); } public bool IsGenericInstance { get { return genericArguments != null; } } public KeyValuePair[] GenericArguments { get { return genericArguments; } } public IType ElementType { get { return elementType; } } public bool HasGenericParameter { get { return clrType.ContainsGenericParameters; } } public Type TypeForCLR { get { return clrType; } } public Type ReflectionType { get { if (wraperType == null) wraperType = new ILRuntimeWrapperType(this); return wraperType; } } public IType ByRefType { get { return byRefType; } } public IType ArrayType { get { return arrayType; } } public bool IsArray { get;private set; } public bool IsValueType { get { return isValueType; } } public bool IsDelegate { get { return isDelegate; } } public bool IsPrimitive { get { return isPrimitive; } } public string FullName { get { return clrType.FullName; } } public string Name { get { return clrType.Name; } } public IType BaseType { get { if (!isBaseTypeInitialized) InitializeBaseType(); return baseType; } } public IType[] Implements { get { if (!interfaceInitialized) InitializeInterfaces(); return interfaces; } } public ValueTypeBinder ValueTypeBinder { get { if (clrType.IsValueType) { if (!valueTypeBinderGot) { valueTypeBinderGot = true; if (appdomain.ValueTypeBinders.TryGetValue(clrType, out valueTypeBinder)) valueTypeBinder.CLRType = this; } return valueTypeBinder; } else return null; } } public object PerformMemberwiseClone(object target) { if (memberwiseCloneDelegate == null) { if (!AppDomain.MemberwiseCloneMap.TryGetValue(this.clrType, out memberwiseCloneDelegate)) { var memberwiseClone = clrType.GetMethod("MemberwiseClone", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); if (memberwiseClone != null) { memberwiseCloneDelegate = (ref object t) => memberwiseClone.Invoke(t, null); } else { throw new InvalidOperationException("Memberwise clone method not found for " + clrType.FullName); } } } return memberwiseCloneDelegate(ref target); } void InitializeBaseType() { baseType = appdomain.GetType(clrType.BaseType); if (baseType.TypeForCLR == typeof(Enum) || baseType.TypeForCLR == typeof(object) || baseType.TypeForCLR == typeof(ValueType) || baseType.TypeForCLR == typeof(System.Enum)) {//都是这样,无所谓 baseType = null; } isBaseTypeInitialized = true; } void InitializeInterfaces() { interfaceInitialized = true; var arr = clrType.GetInterfaces(); if (arr.Length >0) { interfaces = new IType[arr.Length]; for (int i = 0; i < interfaces.Length; i++) { interfaces[i] = appdomain.GetType(arr[i]); } } } public object GetFieldValue(int hash, object target) { if (fieldMapping == null) InitializeFields(); var getter = GetFieldGetter(hash); if (getter != null) { return getter(ref target); } var fieldinfo = GetField(hash); if (fieldinfo != null) { return fieldinfo.GetValue(target); } return null; } public void SetStaticFieldValue(int hash, object value) { if (fieldMapping == null) InitializeFields(); var setter = GetFieldSetter(hash); object target = null; if (setter != null) { setter(ref target, value); return; } var fieldInfo = GetField(hash); if (fieldInfo != null) { fieldInfo.SetValue(null, value); } } public unsafe void SetFieldValue(int hash, ref object target, object value) { if (fieldMapping == null) InitializeFields(); var setter = GetFieldSetter(hash); if (setter != null) { setter(ref target, value); return; } var fieldInfo = GetField(hash); if (fieldInfo != null) { fieldInfo.SetValue(target, value); } } private CLRFieldGetterDelegate GetFieldGetter(int hash) { var dic = fieldGetterCache; CLRFieldGetterDelegate res; if (dic != null && dic.TryGetValue(hash, out res)) return res; else if (BaseType != null) return ((CLRType)BaseType).GetFieldGetter(hash); else return null; } private CLRFieldSetterDelegate GetFieldSetter(int hash) { var dic = fieldSetterCache; CLRFieldSetterDelegate res; if (dic != null && dic.TryGetValue(hash, out res)) return res; else if (BaseType != null) return ((CLRType)BaseType).GetFieldSetter(hash); else return null; } public FieldInfo GetField(int hash) { var dic = Fields; FieldInfo res; if (dic.TryGetValue(hash, out res)) return res; else if (BaseType != null) return ((CLRType)BaseType).GetField(hash); else return null; } void InitializeMethods() { methods = new Dictionary>(); constructors = new List(); foreach (var i in clrType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) { if (i.IsPrivate) continue; List lst; if (!methods.TryGetValue(i.Name, out lst)) { lst = new List(); methods[i.Name] = lst; } lst.Add(new CLRMethod(i, this, appdomain)); } foreach (var i in clrType.GetConstructors()) { constructors.Add(new CLRMethod(i, this, appdomain)); } } public List GetMethods() { if (methods == null) InitializeMethods(); List res = new List(); foreach (var i in methods) { foreach (var j in i.Value) res.Add(j); } return res; } public IMethod GetVirtualMethod(IMethod method) { var m = GetMethod(method.Name, method.Parameters, null, method.ReturnType); if (m == null) { return method; } else return m; } void InitializeFields() { fieldMapping = new Dictionary(); fieldInfoCache = new Dictionary(); var fields = clrType.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static); int idx = 0; bool hasValueTypeBinder = ValueTypeBinder != null; if (hasValueTypeBinder) { fieldIdxMapping = new Dictionary(); orderedFieldTypes = new IType[fields.Length]; } foreach (var i in fields) { int hashCode = i.GetHashCode(); if (i.IsPublic || i.IsFamily || hasValueTypeBinder) { fieldMapping[i.Name] = hashCode; fieldInfoCache[hashCode] = i; } if (hasValueTypeBinder && !i.IsStatic) { orderedFieldTypes[idx] = appdomain.GetType(i.FieldType); fieldIdxMapping[hashCode] = idx++; } CLRFieldGetterDelegate getter; if (AppDomain.FieldGetterMap.TryGetValue(i, out getter)) { if (fieldGetterCache == null) fieldGetterCache = new Dictionary(); fieldGetterCache[hashCode] = getter; } CLRFieldSetterDelegate setter; if (AppDomain.FieldSetterMap.TryGetValue(i, out setter)) { if (fieldSetterCache == null) fieldSetterCache = new Dictionary(); fieldSetterCache[hashCode] = setter; } } } public int GetFieldIndex(object token) { if (fieldMapping == null) InitializeFields(); int idx; int hashCode = token.GetHashCode(); if (fieldTokenMapping == null) fieldTokenMapping = new Dictionary(); if (fieldTokenMapping.TryGetValue(hashCode, out idx)) return idx; FieldReference f = token as FieldReference; if (fieldMapping.TryGetValue(f.Name, out idx)) { fieldTokenMapping[hashCode] = idx; return idx; } return -1; } public IType FindGenericArgument(string key) { if (genericArguments != null) { foreach (var i in genericArguments) { if (i.Key == key) return i.Value; } } return null; } public IMethod GetMethod(string name, int paramCount, bool declaredOnly = false) { if (methods == null) InitializeMethods(); List lst; if (methods.TryGetValue(name, out lst)) { foreach (var i in lst) { if (i.ParameterCount == paramCount) return i; } } return null; } public IMethod GetMethod(string name, List param, IType[] genericArguments, IType returnType = null, bool declaredOnly = false) { if (methods == null) InitializeMethods(); List lst; IMethod genericMethod = null; if (methods.TryGetValue(name, out lst)) { foreach (var i in lst) { if (i.ParameterCount == param.Count) { bool match = true; if (genericArguments != null && i.GenericParameterCount == genericArguments.Length) { for (int j = 0; j < param.Count; j++) { var p = i.Parameters[j].TypeForCLR; var q = param[j].TypeForCLR; if (i.Parameters[j].HasGenericParameter) { //TODO should match the generic parameters; continue; } if (q != p) { match = false; break; } } if (match && genericMethod == null) { genericMethod = i; } } else { if (genericArguments == null) match = i.GenericArguments == null; else { if (i.GenericArguments == null) match = false; else match = i.GenericArguments.Length == genericArguments.Length; } for (int j = 0; j < param.Count; j++) { var typeA = param[j].TypeForCLR.IsByRef ? param[j].TypeForCLR.GetElementType() : param[j].TypeForCLR; var typeB = i.Parameters[j].TypeForCLR.IsByRef ? i.Parameters[j].TypeForCLR.GetElementType() : i.Parameters[j].TypeForCLR; if (typeA != typeB) { match = false; break; } } if (match) { match = returnType == null || i.ReturnType.TypeForCLR == returnType.TypeForCLR; } if (match) { if (i.IsGenericInstance) { if (i.GenericArguments.Length == genericArguments.Length) { for (int j = 0; j < genericArguments.Length; j++) { if (i.GenericArguments[j] != genericArguments[j]) { match = false; break; } } if (match) return i; } } else return i; } } } } } if (genericArguments != null && genericMethod != null) { var m = genericMethod.MakeGenericMethod(genericArguments); lst.Add((CLRMethod)m); return m; } return null; } public bool CanAssignTo(IType type) { if (this == type) { return true; } else return false; } public IMethod GetConstructor(List param) { if (constructors == null) InitializeMethods(); foreach (var i in constructors) { if (i.ParameterCount == param.Count) { bool match = true; for (int j = 0; j < param.Count; j++) { if (param[j].TypeForCLR != i.Parameters[j].TypeForCLR) { match = false; break; } } if (match) { return i; } } } return null; } public IType MakeGenericInstance(KeyValuePair[] genericArguments) { if (genericInstances == null) genericInstances = new List(); foreach (var i in genericInstances) { bool match = true; for (int j = 0; j < genericArguments.Length; j++) { if (i.genericArguments[j].Value != genericArguments[j].Value) { match = false; break; } } if (match) return i; } Type[] args = new Type[genericArguments.Length]; for (int i = 0; i < genericArguments.Length; i++) { args[i] = genericArguments[i].Value.TypeForCLR; } Type newType = clrType.MakeGenericType(args); var res = new CLRType(newType, appdomain); res.genericArguments = genericArguments; genericInstances.Add(res); return res; } public object CreateDefaultInstance() { if (createDefaultInstanceDelegate == null) { if (!AppDomain.CreateDefaultInstanceMap.TryGetValue(clrType, out createDefaultInstanceDelegate)) { createDefaultInstanceDelegate = () => Activator.CreateInstance(TypeForCLR); } } return createDefaultInstanceDelegate(); } public object CreateArrayInstance(int size) { if (createArrayInstanceDelegate == null) { if (!AppDomain.CreateArrayInstanceMap.TryGetValue(clrType, out createArrayInstanceDelegate)) { createArrayInstanceDelegate = s => Array.CreateInstance(TypeForCLR, s); } } return createArrayInstanceDelegate(size); } public IType MakeByRefType() { if (byRefType == null) { Type t = clrType.MakeByRefType(); byRefType = new CLRType(t, appdomain); } return byRefType; } public IType MakeArrayType() { if (arrayType == null) { Type t = clrType.MakeArrayType(); arrayType = new CLRType(t, appdomain); ((CLRType)arrayType).elementType = this; ((CLRType)arrayType).IsArray = true; } return arrayType; } public IType ResolveGenericType(IType contextType) { throw new NotImplementedException(); } public override int GetHashCode() { if (hashCode == -1) hashCode = System.Threading.Interlocked.Add(ref instance_id, 1); return hashCode; } public override string ToString() { return clrType.ToString(); } } } ================================================ FILE: SGFUnity/ILRuntime/CLR/TypeSystem/ILGenericParameterType.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.CLR.TypeSystem { class ILGenericParameterType : IType { string name; ILGenericParameterType arrayType; public ILGenericParameterType(string name) { this.name = name; } public bool IsGenericInstance { get { return false; } } public KeyValuePair[] GenericArguments { get { return null; } } public bool HasGenericParameter { get { return true; } } public Type TypeForCLR { get { return typeof(ILGenericParameterType); } } public string FullName { get { return name; } } public Runtime.Enviorment.AppDomain AppDomain { get { return null; } } public Method.IMethod GetMethod(string name, int paramCount, bool declaredOnly = false) { return null; } public Method.IMethod GetMethod(string name, List param, IType[] genericArguments, IType returnType = null, bool declaredOnly = false) { return null; } public List GetMethods() { return null; } public Method.IMethod GetConstructor(List param) { return null; } public bool CanAssignTo(IType type) { return false; } public IType MakeGenericInstance(KeyValuePair[] genericArguments) { return null; } public IType ResolveGenericType(IType contextType) { throw new NotImplementedException(); } public int GetFieldIndex(object token) { return -1; } public IType FindGenericArgument(string key) { return null; } public IType ByRefType { get { throw new NotImplementedException(); } } public IType MakeByRefType() { return this; } public IType ArrayType { get { return arrayType; } } public IType MakeArrayType() { if (arrayType == null) arrayType = new ILGenericParameterType(name + "[]"); return arrayType; } public bool IsValueType { get { throw new NotImplementedException(); } } public bool IsPrimitive { get { return false; } } public string Name { get { return name; } } public bool IsDelegate { get { return false; } } public Type ReflectionType { get { throw new NotImplementedException(); } } public IType BaseType { get { return null; } } public Method.IMethod GetVirtualMethod(Method.IMethod method) { return method; } public bool IsArray { get { return false; } } public IType[] Implements { get { return null; } } } } ================================================ FILE: SGFUnity/ILRuntime/CLR/TypeSystem/ILType.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using Mono.Cecil; using ILRuntime.Runtime.Enviorment; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Intepreter; using ILRuntime.Reflection; namespace ILRuntime.CLR.TypeSystem { public class ILType : IType { Dictionary> methods; TypeReference typeRef; TypeDefinition definition; ILRuntime.Runtime.Enviorment.AppDomain appdomain; ILMethod staticConstructor; List constructors; IType[] fieldTypes; FieldDefinition[] fieldDefinitions; IType[] staticFieldTypes; FieldDefinition[] staticFieldDefinitions; Dictionary fieldMapping; Dictionary staticFieldMapping; ILTypeStaticInstance staticInstance; Dictionary fieldTokenMapping = new Dictionary(); int fieldStartIdx = -1; int totalFieldCnt = -1; KeyValuePair[] genericArguments; IType baseType, byRefType, arrayType, enumType, elementType; Type arrayCLRType, byRefCLRType; IType[] interfaces; bool baseTypeInitialized = false; bool interfaceInitialized = false; List genericInstances; bool isDelegate; ILRuntimeType reflectionType; IType firstCLRBaseType, firstCLRInterface; int hashCode = -1; static int instance_id = 0x10000000; public TypeDefinition TypeDefinition { get { return definition; } } public TypeReference TypeReference { get { return typeRef; } set { typeRef = value; RetriveDefinitino(value); } } public IType BaseType { get { if (!baseTypeInitialized) InitializeBaseType(); return baseType; } } public IType[] Implements { get { if (!interfaceInitialized) InitializeInterfaces(); return interfaces; } } public ILTypeStaticInstance StaticInstance { get { if (fieldMapping == null) InitializeFields(); if (methods == null) InitializeMethods(); return staticInstance; } } public IType[] FieldTypes { get { if (fieldMapping == null) InitializeFields(); return fieldTypes; } } public IType[] StaticFieldTypes { get { if (fieldMapping == null) InitializeFields(); return staticFieldTypes; } } public FieldDefinition[] StaticFieldDefinitions { get { if (fieldMapping == null) InitializeFields(); return staticFieldDefinitions; } } public Dictionary FieldMapping { get { if (fieldMapping == null) InitializeFields(); return fieldMapping; } } public IType FirstCLRBaseType { get { if (!baseTypeInitialized) InitializeBaseType(); return firstCLRBaseType; } } public IType FirstCLRInterface { get { if (!interfaceInitialized) InitializeInterfaces(); return firstCLRInterface; } } public bool HasGenericParameter { get { return definition.HasGenericParameters && genericArguments == null; } } public Dictionary StaticFieldMapping { get { return staticFieldMapping; } } public ILRuntime.Runtime.Enviorment.AppDomain AppDomain { get { return appdomain; } } internal int FieldStartIndex { get { if (fieldStartIdx < 0) { if (BaseType != null) { if (BaseType is ILType) { fieldStartIdx = ((ILType)BaseType).TotalFieldCount; } else fieldStartIdx = 0; } else fieldStartIdx = 0; } return fieldStartIdx; } } public int TotalFieldCount { get { if (totalFieldCnt < 0) { if (fieldMapping == null) InitializeFields(); if (BaseType != null) { if (BaseType is ILType) { totalFieldCnt = ((ILType)BaseType).TotalFieldCount + fieldTypes.Length; } else totalFieldCnt = fieldTypes.Length; } else totalFieldCnt = fieldTypes.Length; } return totalFieldCnt; } } /// /// 初始化IL类型 /// /// MONO返回的类型定义 /// ILdomain public ILType(TypeReference def, Runtime.Enviorment.AppDomain domain) { this.typeRef = def; RetriveDefinitino(def); appdomain = domain; } /// /// 加载类型 /// /// void RetriveDefinitino(TypeReference def) { if (!def.IsGenericParameter) { if (def is TypeSpecification) RetriveDefinitino(def.GetElementType()); else definition = def as TypeDefinition; } } public bool IsGenericInstance { get { return genericArguments != null; } } public KeyValuePair[] GenericArguments { get { return genericArguments; } } public IType ElementType { get { return elementType; } } public bool IsArray { get; private set; } private bool? isValueType; public bool IsValueType { get { if (isValueType == null) isValueType = definition.IsValueType; return isValueType.Value; } } public bool IsDelegate { get { if (!baseTypeInitialized) InitializeBaseType(); return isDelegate; } } public bool IsPrimitive { get { return false; } } public Type TypeForCLR { get { if (!baseTypeInitialized) InitializeBaseType(); if (typeRef is ArrayType) { return arrayCLRType; } else if (typeRef is ByReferenceType) { return byRefCLRType; } else if (definition.IsEnum) { if (enumType == null) InitializeFields(); return enumType.TypeForCLR; } else if (FirstCLRBaseType != null && FirstCLRBaseType is CrossBindingAdaptor) { return ((CrossBindingAdaptor)FirstCLRBaseType).RuntimeType.TypeForCLR; } else if (FirstCLRInterface != null && FirstCLRInterface is CrossBindingAdaptor) { return ((CrossBindingAdaptor)FirstCLRInterface).RuntimeType.TypeForCLR; } else return typeof(ILTypeInstance); } } public Type ReflectionType { get { if (reflectionType == null) reflectionType = new ILRuntimeType(this); return reflectionType; } } public IType ByRefType { get { return byRefType; } } public IType ArrayType { get { return arrayType; } } public bool IsEnum { get { return definition.IsEnum; } } public string FullName { get { return typeRef.FullName; } } public string Name { get { return typeRef.Name; } } public List GetMethods() { if (methods == null) InitializeMethods(); List res = new List(); foreach (var i in methods) { foreach (var j in i.Value) res.Add(j); } return res; } void InitializeInterfaces() { interfaceInitialized = true; if (definition.HasInterfaces) { interfaces = new IType[definition.Interfaces.Count]; for (int i = 0; i < interfaces.Length; i++) { interfaces[i] = appdomain.GetType(definition.Interfaces[i], this, null); //only one clrInterface is valid if (interfaces[i] is CLRType && firstCLRInterface == null) { CrossBindingAdaptor adaptor; if (appdomain.CrossBindingAdaptors.TryGetValue(interfaces[i].TypeForCLR, out adaptor)) { interfaces[i] = adaptor; firstCLRInterface = adaptor; } else throw new TypeLoadException("Cannot find Adaptor for:" + interfaces[i].TypeForCLR.ToString()); } } } } void InitializeBaseType() { if (definition.BaseType != null) { bool specialProcess = false; List spIdx = null; if (definition.BaseType.IsGenericInstance) { GenericInstanceType git = definition.BaseType as GenericInstanceType; var elementType = appdomain.GetType(definition.BaseType.GetElementType(), this, null); if (elementType is CLRType) { for (int i = 0; i < git.GenericArguments.Count; i++) { var ga = git.GenericArguments[i]; if (ga == typeRef) { specialProcess = true; if (spIdx == null) spIdx = new List(); spIdx.Add(i); } } } } if (specialProcess) { //如果泛型参数是自身,则必须要特殊处理,否则会StackOverflow var elementType = appdomain.GetType(definition.BaseType.GetElementType(), this, null); foreach (var i in appdomain.CrossBindingAdaptors) { if (i.Key.IsGenericType && !i.Key.IsGenericTypeDefinition) { var gd = i.Key.GetGenericTypeDefinition(); if (gd == elementType.TypeForCLR) { var ga = i.Key.GetGenericArguments(); bool match = true; foreach (var j in spIdx) { if (ga[j] != i.Value.AdaptorType) { match = false; break; } } if (match) { baseType = i.Value; break; } } } } if (baseType == null) { throw new TypeLoadException("Cannot find Adaptor for:" + definition.BaseType.FullName); } } else { baseType = appdomain.GetType(definition.BaseType, this, null); if (baseType is CLRType) { if (baseType.TypeForCLR == typeof(Enum) || baseType.TypeForCLR == typeof(object) || baseType.TypeForCLR == typeof(ValueType) || baseType.TypeForCLR == typeof(System.Enum)) {//都是这样,无所谓 baseType = null; } else if (baseType.TypeForCLR == typeof(MulticastDelegate)) { baseType = null; isDelegate = true; } else { CrossBindingAdaptor adaptor; if (appdomain.CrossBindingAdaptors.TryGetValue(baseType.TypeForCLR, out adaptor)) { baseType = adaptor; } else throw new TypeLoadException("Cannot find Adaptor for:" + baseType.TypeForCLR.ToString()); //继承了其他系统类型 //env.logger.Log_Error("ScriptType:" + Name + " Based On a SystemType:" + BaseType.Name); //HasSysBase = true; //throw new Exception("不得继承系统类型,脚本类型系统和脚本类型系统是隔离的"); } } } } var curBase = baseType; while (curBase is ILType) { curBase = curBase.BaseType; } firstCLRBaseType = curBase; baseTypeInitialized = true; } public IMethod GetMethod(string name) { if (methods == null) InitializeMethods(); List lst; if (methods.TryGetValue(name, out lst)) { return lst[0]; } return null; } public IMethod GetMethod(string name, int paramCount, bool declaredOnly = false) { if (methods == null) InitializeMethods(); List lst; if (methods.TryGetValue(name, out lst)) { foreach (var i in lst) { if (i.ParameterCount == paramCount) return i; } } if (declaredOnly) return null; else { //skip clr base type, this doesn't make any sense if (BaseType != null && !(BaseType is CrossBindingAdaptor)) return BaseType.GetMethod(name, paramCount, false); else return null; } } void InitializeMethods() { methods = new Dictionary>(); constructors = new List(); foreach (var i in definition.Methods) { if (i.IsConstructor) { if (i.IsStatic) staticConstructor = new ILMethod(i, this, appdomain); else constructors.Add(new ILMethod(i, this, appdomain)); } else { List lst; if (!methods.TryGetValue(i.Name, out lst)) { lst = new List(); methods[i.Name] = lst; } var m = new ILMethod(i, this, appdomain); lst.Add(new ILMethod(i, this, appdomain)); } } if (staticConstructor != null && (!TypeReference.HasGenericParameters || IsGenericInstance)) { appdomain.Invoke(staticConstructor, null, null); } } public IMethod GetVirtualMethod(IMethod method) { IType[] genericArguments = null; if (method.IsGenericInstance) { if (method is ILMethod) { genericArguments = ((ILMethod)method).GenericArugmentsArray; } else { genericArguments = ((CLRMethod)method).GenericArguments; } } var m = GetMethod(method.Name, method.Parameters, genericArguments, method.ReturnType, true); if (m == null) { if (BaseType != null) { return BaseType.GetVirtualMethod(method); } else return null;//BaseType == null means base type is Object or Enum } else if (m.IsGenericInstance == method.IsGenericInstance) return m; else return method; } public IMethod GetMethod(string name, List param, IType[] genericArguments, IType returnType = null, bool declaredOnly = false) { if (methods == null) InitializeMethods(); List lst; IMethod genericMethod = null; if (methods.TryGetValue(name, out lst)) { for (var idx = 0; idx < lst.Count; idx++) { var i = lst[idx]; int pCnt = param != null ? param.Count : 0; if (i.ParameterCount == pCnt) { bool match = true; if (genericArguments != null && i.GenericParameterCount == genericArguments.Length) { genericMethod = CheckGenericParams(i, param, ref match); } else { match = CheckGenericArguments(i, genericArguments); if (!match) continue; for (int j = 0; j < pCnt; j++) { if (param[j] != i.Parameters[j]) { match = false; break; } } if (match) { match = returnType == null || i.ReturnType == returnType; } if (match) return i; } } } } if (genericArguments != null && genericMethod != null) { var m = genericMethod.MakeGenericMethod(genericArguments); lst.Add((ILMethod)m); return m; } if (declaredOnly) return null; else { if (BaseType != null) return BaseType.GetMethod(name, param, genericArguments, returnType, false); else return null; } } bool CheckGenericArguments(ILMethod i, IType[] genericArguments) { if (genericArguments == null) { return i.GenericArguments == null; } else { if (i.GenericArguments == null) return false; else if (i.GenericArguments.Length != genericArguments.Length) return false; if (i.GenericArguments.Length == genericArguments.Length) { for (int j = 0; j < genericArguments.Length; j++) { if (i.GenericArguments[j].Value != genericArguments[j]) return false; } return true; } else return false; } } ILMethod CheckGenericParams(ILMethod i, List param, ref bool match) { ILMethod genericMethod = null; if (param != null) { for (int j = 0; j < param.Count; j++) { var p = i.Parameters[j]; if (p.HasGenericParameter) { //TODO should match the generic parameters; continue; } if (param[j] != p) { match = false; break; } } } if (match) { genericMethod = i; } return genericMethod; } public List GetConstructors() { if (constructors == null) InitializeMethods(); return constructors; } public IMethod GetStaticConstroctor() { if (constructors == null) InitializeMethods(); return staticConstructor; } public IMethod GetConstructor(int paramCnt) { if (constructors == null) InitializeMethods(); foreach (var i in constructors) { if (i.ParameterCount == paramCnt) { return i; } } return null; } public IMethod GetConstructor(List param) { if (constructors == null) InitializeMethods(); foreach (var i in constructors) { if (i.ParameterCount == param.Count) { bool match = true; for (int j = 0; j < param.Count; j++) { if (param[j] != i.Parameters[j]) { match = false; break; } } if (match) return i; } } return null; } public int GetFieldIndex(object token) { if (fieldMapping == null) InitializeFields(); int idx; int hashCode = token.GetHashCode(); if (fieldTokenMapping.TryGetValue(hashCode, out idx)) return idx; FieldReference f = token as FieldReference; if (staticFieldMapping != null && staticFieldMapping.TryGetValue(f.Name, out idx)) { fieldTokenMapping[hashCode] = idx; return idx; } if (fieldMapping.TryGetValue(f.Name, out idx)) { fieldTokenMapping[hashCode] = idx; return idx; } return -1; } public IType GetField(string name, out int fieldIdx) { if (fieldMapping == null) InitializeFields(); if (fieldMapping.TryGetValue(name, out fieldIdx)) { return fieldTypes[fieldIdx - FieldStartIndex]; } else if (BaseType != null && BaseType is ILType) { return ((ILType)BaseType).GetField(name, out fieldIdx); } else return null; } public IType GetField(int fieldIdx, out FieldDefinition fd) { if (fieldMapping == null) InitializeFields(); if (fieldIdx < FieldStartIndex) return ((ILType)BaseType).GetField(fieldIdx, out fd); else { fd = fieldDefinitions[fieldIdx - FieldStartIndex]; return fieldTypes[fieldIdx - FieldStartIndex]; } } void InitializeFields() { fieldMapping = new Dictionary(); fieldTypes = new IType[definition.Fields.Count]; fieldDefinitions = new FieldDefinition[definition.Fields.Count]; var fields = definition.Fields; int idx = FieldStartIndex; int idxStatic = 0; for (int i = 0; i < fields.Count; i++) { var field = fields[i]; if (field.IsStatic) { //It makes no sence to initialize if (!TypeReference.HasGenericParameters || IsGenericInstance) { if (staticFieldTypes == null) { staticFieldTypes = new IType[definition.Fields.Count]; staticFieldDefinitions = new FieldDefinition[definition.Fields.Count]; staticFieldMapping = new Dictionary(); } staticFieldMapping[field.Name] = idxStatic; staticFieldDefinitions[idxStatic] = field; if (field.FieldType.IsGenericParameter) { staticFieldTypes[idxStatic] = FindGenericArgument(field.FieldType.Name); } else staticFieldTypes[idxStatic] = appdomain.GetType(field.FieldType, this, null); idxStatic++; } } else { fieldMapping[field.Name] = idx; fieldDefinitions[idx - FieldStartIndex] = field; if (field.FieldType.IsGenericParameter) { fieldTypes[idx - FieldStartIndex] = FindGenericArgument(field.FieldType.Name); } else fieldTypes[idx - FieldStartIndex] = appdomain.GetType(field.FieldType, this, null); if (IsEnum) { enumType = fieldTypes[idx - FieldStartIndex]; } idx++; } } Array.Resize(ref fieldTypes, idx - FieldStartIndex); Array.Resize(ref fieldDefinitions, idx - FieldStartIndex); if (staticFieldTypes != null) { Array.Resize(ref staticFieldTypes, idxStatic); Array.Resize(ref staticFieldDefinitions, idxStatic); staticInstance = new ILTypeStaticInstance(this); } } public IType FindGenericArgument(string key) { if (genericArguments != null) { foreach (var i in genericArguments) { if (i.Key == key) return i.Value; } } return null; } public bool CanAssignTo(IType type) { bool res = false; if (this == type) { return true; } if (BaseType != null) { res = BaseType.CanAssignTo(type); if (res) return true; } if (Implements != null) { for (int i = 0; i < interfaces.Length; i++) { var im = interfaces[i]; res = im.CanAssignTo(type); if (res) return true; } } return res; } public ILTypeInstance Instantiate(bool callDefaultConstructor = true) { var res = new ILTypeInstance(this); if (callDefaultConstructor) { var m = GetConstructor(CLR.Utils.Extensions.EmptyParamList); if (m != null) { appdomain.Invoke(m, res, null); } } return res; } public IType MakeGenericInstance(KeyValuePair[] genericArguments) { if (genericInstances == null) genericInstances = new List(); foreach (var i in genericInstances) { bool match = true; for (int j = 0; j < genericArguments.Length; j++) { if (i.genericArguments[j].Value != genericArguments[j].Value) { match = false; break; } } if (match) return i; } var res = new ILType(definition, appdomain); res.genericArguments = genericArguments; genericInstances.Add(res); return res; } public IType MakeByRefType() { if (byRefType == null) { var def = new ByReferenceType(typeRef); byRefType = new ILType(def, appdomain); ((ILType)byRefType).elementType = this; ((ILType)byRefType).byRefCLRType = this.TypeForCLR.MakeByRefType(); } return byRefType; } public IType MakeArrayType() { if (arrayType == null) { var def = new ArrayType(typeRef); arrayType = new ILType(def, appdomain); ((ILType)arrayType).IsArray = true; ((ILType)arrayType).elementType = this; ((ILType)arrayType).arrayCLRType = this.TypeForCLR.MakeArrayType(); } return arrayType; } public IType ResolveGenericType(IType contextType) { var ga = contextType.GenericArguments; IType[] kv = new IType[definition.GenericParameters.Count]; for (int i = 0; i < kv.Length; i++) { var gp = definition.GenericParameters[i]; string name = gp.Name; foreach (var j in ga) { if (j.Key == name) { kv[i] = j.Value; break; } } } foreach (var i in genericInstances) { bool match = true; for (int j = 0; j < kv.Length; j++) { if (i.genericArguments[j].Value != kv[j]) { match = false; break; } } if (match) return i; } return null; } public override int GetHashCode() { if (hashCode == -1) hashCode = System.Threading.Interlocked.Add(ref instance_id, 1); return hashCode; } public override string ToString() { return FullName; } } } ================================================ FILE: SGFUnity/ILRuntime/CLR/TypeSystem/IType.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.Method; namespace ILRuntime.CLR.TypeSystem { public interface IType { bool IsGenericInstance { get; } KeyValuePair[] GenericArguments { get; } Type TypeForCLR { get; } Type ReflectionType { get; } IType BaseType { get; } IType[] Implements { get; } IType ByRefType { get; } IType ArrayType { get; } string FullName { get; } string Name { get; } bool IsArray { get; } bool IsValueType { get; } bool IsDelegate { get; } bool IsPrimitive { get; } bool HasGenericParameter { get; } ILRuntime.Runtime.Enviorment.AppDomain AppDomain { get; } /// /// Get a specified Method in this type /// /// Name of the Type /// Parameter count /// True to search the methods decleared in this type only, false to search base types. /// IMethod GetMethod(string name, int paramCount, bool declaredOnly = false); /// /// Get a specified Method in this type /// /// Name of the Type /// List of parameter's types /// List of Generic Arguments /// Return Type /// True to search the methods decleared in this type only, false to search base types. /// IMethod GetMethod(string name, List param, IType[] genericArguments, IType returnType = null, bool declaredOnly = false); IMethod GetVirtualMethod(IMethod method); List GetMethods(); int GetFieldIndex(object token); IMethod GetConstructor(List param); bool CanAssignTo(IType type); IType MakeGenericInstance(KeyValuePair[] genericArguments); IType MakeByRefType(); IType MakeArrayType(); IType FindGenericArgument(string key); IType ResolveGenericType(IType contextType); } } ================================================ FILE: SGFUnity/ILRuntime/CLR/Utils/Extensions.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.Other; using Mono.Cecil; using ILRuntime.Runtime.Intepreter; namespace ILRuntime.CLR.Utils { public delegate TResult Func(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); public static class Extensions { public static List EmptyParamList = new List(); public static List GetParamList(this MethodReference def, ILRuntime.Runtime.Enviorment.AppDomain appdomain, IType contextType, IMethod contextMethod, IType[] genericArguments) { if (def.HasParameters) { List param = new List(); var dt = appdomain.GetType(def.DeclaringType, contextType, contextMethod); foreach (var i in def.Parameters) { IType t = null; t = appdomain.GetType(i.ParameterType, dt, null); if (t == null && def.IsGenericInstance) { GenericInstanceMethod gim = (GenericInstanceMethod)def; string name = i.ParameterType.IsByReference ? i.ParameterType.GetElementType().FullName : i.ParameterType.FullName; for (int j = 0; j < gim.GenericArguments.Count; j++) { var gp = gim.ElementMethod.GenericParameters[j]; var ga = gim.GenericArguments[j]; if (name == gp.Name) { t = appdomain.GetType(ga, contextType, contextMethod); if (t == null && genericArguments != null) t = genericArguments[j]; break; } else if (name.Contains(gp.Name)) { if (name == gp.Name) { name = ga.FullName; } else if (name == gp.Name + "[]") { name = ga.FullName + "[]"; } else { /*name = name.Replace("<" + gp.Name + ">", "<" + ga.FullName + ">"); name = name.Replace("<" + gp.Name + "[", "<" + ga.FullName + "["); name = name.Replace("<" + gp.Name + ",", "<" + ga.FullName + ","); name = name.Replace("," + gp.Name + ">", "," + ga.FullName + ">"); name = name.Replace("," + gp.Name + "[", "," + ga.FullName + "["); name = name.Replace("," + gp.Name + ",", "," + ga.FullName + ","); name = name.Replace("," + gp.Name + "[", "," + ga.FullName + "[");*/ name = ReplaceGenericArgument(name, gp.Name, ga.FullName); } } } if (t == null) t = appdomain.GetType(name); } param.Add(t); } return param; } else return EmptyParamList; } static string ReplaceGenericArgument(string typename, string argumentName, string argumentType) { string baseType; StringBuilder sb = new StringBuilder(); List ga; bool isArray; Runtime.Enviorment.AppDomain.ParseGenericType(typename, out baseType, out ga, out isArray); if (baseType == argumentName) sb.Append(argumentType); else sb.Append(baseType); if (ga != null && ga.Count > 0) { sb.Append("<"); bool isFirst = true; foreach(var i in ga) { if (isFirst) isFirst = false; else sb.Append(","); sb.Append(ReplaceGenericArgument(i, argumentName, argumentType)); } sb.Append(">"); } if (isArray) sb.Append("[]"); return sb.ToString(); } [Flags] public enum TypeFlags { Default = 0, IsPrimitive = 0x1, IsByRef = 0x2, IsEnum = 0x4, IsDelegate = 0x8, IsValueType = 0x10, } private static readonly Dictionary typeFlags = new Dictionary(new ByReferenceKeyComparer()); public static bool FastIsEnum(this Type pt) { return (pt.GetTypeFlags() & TypeFlags.IsEnum) != 0; } public static bool FastIsByRef(this Type pt) { return (pt.GetTypeFlags() & TypeFlags.IsByRef) != 0; } public static bool FastIsPrimitive(this Type pt) { return (pt.GetTypeFlags() & TypeFlags.IsPrimitive) != 0; } public static bool FastIsValueType(this Type pt) { return (pt.GetTypeFlags() & TypeFlags.IsValueType) != 0; } public static TypeFlags GetTypeFlags(this Type pt) { var result = TypeFlags.Default; if (!typeFlags.TryGetValue(pt, out result)) { if (pt.IsPrimitive) { result |= TypeFlags.IsPrimitive; } if (pt == typeof(Delegate) || pt.IsSubclassOf(typeof(Delegate))) { result |= TypeFlags.IsDelegate; } if (pt.IsByRef) { result |= TypeFlags.IsByRef; } if (pt.IsEnum) { result |= TypeFlags.IsEnum; } if (pt.IsValueType) { result |= TypeFlags.IsValueType; } typeFlags[pt] = result; } return result; } public static object CheckCLRTypes(this Type pt, object obj) { if (obj == null) return null; var typeFlags = GetTypeFlags(pt); if ((typeFlags & TypeFlags.IsPrimitive) != 0 && pt != typeof(int)) { if (pt == typeof(bool) && !(obj is bool)) { obj = (int)obj == 1; } else if (pt == typeof(byte) && !(obj is byte)) obj = (byte)(int)obj; else if (pt == typeof(short) && !(obj is short)) obj = (short)(int)obj; else if (pt == typeof(char) && !(obj is char)) obj = (char)(int)obj; else if (pt == typeof(ushort) && !(obj is ushort)) obj = (ushort)(int)obj; else if (pt == typeof(uint) && !(obj is uint)) obj = (uint)(int)obj; else if (pt == typeof(sbyte) && !(obj is sbyte)) obj = (sbyte)(int)obj; else if (pt == typeof(ulong) && !(obj is ulong)) { obj = (ulong)(long)obj; } } else if (obj is ILRuntime.Reflection.ILRuntimeWrapperType) { obj = ((ILRuntime.Reflection.ILRuntimeWrapperType)obj).RealType; } else if ((typeFlags & TypeFlags.IsDelegate) != 0) { if (obj is Delegate) return obj; if (pt == typeof(Delegate)) return ((IDelegateAdapter)obj).Delegate; return ((IDelegateAdapter)obj).GetConvertor(pt); } else if ((typeFlags & TypeFlags.IsByRef) != 0) { return CheckCLRTypes(pt.GetElementType(), obj); } else if ((typeFlags & TypeFlags.IsEnum) != 0) { return Enum.ToObject(pt, obj); } else if (obj is ILTypeInstance) { var adapter = obj as IDelegateAdapter; if (adapter != null && pt != typeof(ILTypeInstance)) { return adapter.Delegate; } if (!(obj is ILEnumTypeInstance)) { var ins = (ILTypeInstance)obj; if (ins.IsValueType) ins = ins.Clone(); return ins.CLRInstance; } } return obj; } } } ================================================ FILE: SGFUnity/ILRuntime/Other/ByReferenceKeyComparer.cs ================================================ using System.Collections.Generic; using System.Runtime.CompilerServices; namespace ILRuntime.Other { class ByReferenceKeyComparer : IEqualityComparer { public bool Equals(T x, T y) { return object.ReferenceEquals(x, y); } public int GetHashCode(T obj) { return RuntimeHelpers.GetHashCode(obj); } } } ================================================ FILE: SGFUnity/ILRuntime/Other/DelegateExportAttribute.cs ================================================ namespace ILRuntime.Other { /// /// A Delegate Custom Attr, It tells the CodeGenerationTools : this delegate need to register a delegate convertor,when generate ILRuntimeHelper.cs file. /// public class DelegateExportAttribute : System.Attribute { } } ================================================ FILE: SGFUnity/ILRuntime/Other/NeedAdaptorAttribute.cs ================================================ namespace ILRuntime.Other { /// /// A Class Custom Attr, It tells the CodeGenerationTools :there is a class need to generate an adaptor for ILScript /// public class NeedAdaptorAttribute : System.Attribute { } } ================================================ FILE: SGFUnity/ILRuntime/Other/ThreadSafeDictionary.cs ================================================ using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Runtime.Versioning; using System.Threading; namespace ILRuntime.Other { /// /// A thread safe dictionary for internal use /// /// /// class ThreadSafeDictionary : IDictionary { Dictionary dic = new Dictionary(); public Dictionary InnerDictionary { get { return dic; } } public V this[K key] { get { lock(dic) return dic[key]; } set { lock(dic) dic[key] = value; } } public int Count { get { lock(dic) return dic.Count; } } public bool IsReadOnly { get { lock(dic) return IsReadOnly; } } public ICollection Keys { get { throw new NotImplementedException(); } } public ICollection Values { get { throw new NotImplementedException(); } } public void Add(KeyValuePair item) { lock (dic) dic.Add(item.Key, item.Value); } public void Add(K key, V value) { lock(dic) dic.Add(key, value); } public void Clear() { lock(dic) dic.Clear(); } public bool Contains(KeyValuePair item) { lock(dic) return dic.ContainsKey(item.Key); } public bool ContainsKey(K key) { lock(dic) return dic.ContainsKey(key); } public void CopyTo(KeyValuePair[] array, int arrayIndex) { throw new NotImplementedException(); } public IEnumerator> GetEnumerator() { throw new NotImplementedException(); } public bool Remove(KeyValuePair item) { throw new NotImplementedException(); } public bool Remove(K key) { lock(dic) return dic.Remove(key); } public bool TryGetValue(K key, out V value) { lock(dic) return dic.TryGetValue(key, out value); } IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); } } } ================================================ FILE: SGFUnity/ILRuntime/Other/UncheckedList.cs ================================================ using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Runtime.Versioning; using System.Threading; namespace ILRuntime.Other { /// /// This is a copy of the latest .NET framework 4.5 List implementation, with all extraneous checking removed. /// /// [Serializable] public class UncheckedList : IList, ICollection, IEnumerable, IEnumerable, IList, ICollection { private const int _defaultCapacity = 4; private T[] _items; private int _size; private int _version; [NonSerialized] private Object _syncRoot; private static readonly T[] _emptyArray = new T[0]; // Constructs a UncheckedList. The list is initially empty and has a capacity // of zero. Upon adding the first element to the list the capacity is // increased to _defaultCapacity, and then increased in multiples of two // as required. public UncheckedList() { _items = _emptyArray; } // Constructs a UncheckedList with a given initial capacity. The list is // initially empty, but will have room for the given number of elements // before any reallocations are required. // public UncheckedList(int capacity) { if (capacity == 0) _items = _emptyArray; else _items = new T[capacity]; } // Constructs a UncheckedList, copying the contents of the given collection. The // size and capacity of the new list will both be equal to the size of the // given collection. // public UncheckedList(IEnumerable collection) { ICollection c = collection as ICollection; if (c != null) { int count = c.Count; if (count == 0) { _items = _emptyArray; } else { _items = new T[count]; c.CopyTo(_items, 0); _size = count; } } else { _size = 0; _items = _emptyArray; AddEnumerable(collection); } } // Gets and sets the capacity of this list. The capacity is the size of // the internal array used to hold items. When set, the internal // array of the list is reallocated to the given capacity. // public int Capacity { get { return _items.Length; } set { if (value != _items.Length) { if (value > 0) { T[] newItems = new T[value]; if (_size > 0) { Array.Copy(_items, 0, newItems, 0, _size); } _items = newItems; } else { _items = _emptyArray; } } } } // Read-only property describing how many elements are in the UncheckedList. public int Count { get { return _size; } } bool System.Collections.IList.IsFixedSize { get { return false; } } // Is this UncheckedList read-only? bool ICollection.IsReadOnly { get { return false; } } bool System.Collections.IList.IsReadOnly { get { return false; } } // Is this UncheckedList synchronized (thread-safe)? bool System.Collections.ICollection.IsSynchronized { get { return false; } } // Synchronization root for this object. Object System.Collections.ICollection.SyncRoot { get { if (_syncRoot == null) { System.Threading.Interlocked.CompareExchange(ref _syncRoot, new Object(), null); } return _syncRoot; } } // Sets or Gets the element at the given index. // public T this[int index] { get { return _items[index]; } set { _items[index] = value; _version++; } } private static bool IsCompatibleObject(object value) { // Non-null values are fine. Only accept nulls if T is a class or Nullable. // Note that default(T) is not equal to null for value types except when T is Nullable. return ((value is T) || (value == null && default(T) == null)); } Object System.Collections.IList.this[int index] { get { return this[index]; } set { try { this[index] = (T)value; } catch (InvalidCastException) { } } } // Adds the given object to the end of this list. The size of the list is // increased by one. If required, the capacity of the list is doubled // before adding the new element. public void Add(T item) { var array = _items; var size = _size; _version++; if ((uint)size < (uint)array.Length) { _size = size + 1; array[size] = item; } else { AddWithResize(item); } } // Non-inline from UncheckedList.Add to improve its code quality as uncommon path private void AddWithResize(T item) { var size = _size; EnsureCapacity(size + 1); _size = size + 1; _items[size] = item; } int System.Collections.IList.Add(Object item) { try { Add((T)item); } catch (InvalidCastException) { } return Count - 1; } // Adds the elements of the given collection to the end of this list. If // required, the capacity of the list is increased to twice the previous // capacity or the new size, whichever is larger. // public void AddRange(IEnumerable collection) { InsertRange(_size, collection); } public ReadOnlyCollection AsReadOnly() { return new ReadOnlyCollection(this); } // Searches a section of the list for a given element using a binary search // algorithm. Elements of the list are compared to the search value using // the given IComparer interface. If comparer is null, elements of // the list are compared to the search value using the IComparable // interface, which in that case must be implemented by all elements of the // list and the given search value. This method assumes that the given // section of the list is already sorted; if this is not the case, the // result will be incorrect. // // The method returns the index of the given value in the list. If the // list does not contain the given value, the method returns a negative // integer. The bitwise complement operator (~) can be applied to a // negative result to produce the index of the first element (if any) that // is larger than the given search value. This is also the index at which // the search value should be inserted into the list in order for the list // to remain sorted. // // The method uses the Array.BinarySearch method to perform the // search. // public int BinarySearch(int index, int count, T item, IComparer comparer) { if (index < 0) return -1; return Array.BinarySearch(_items, index, count, item, comparer); } public int BinarySearch(T item) { return BinarySearch(0, Count, item, null); } public int BinarySearch(T item, IComparer comparer) { return BinarySearch(0, Count, item, comparer); } // Clears the contents of UncheckedList. public void Clear() { if (!typeof(T).IsValueType) { int size = _size; _size = 0; _version++; if (size > 0) { Array.Clear(_items, 0, size); // Clear the elements so that the gc can reclaim the references. } } else { _size = 0; _version++; } } // Contains returns true if the specified element is in the UncheckedList. // It does a linear, O(n) search. Equality is determined by calling // EqualityComparer.Default.Equals(). public bool Contains(T item) { // PERF: IndexOf calls Array.IndexOf, which internally // calls EqualityComparer.Default.IndexOf, which // is specialized for different types. This // boosts performance since instead of making a // virtual method call each iteration of the loop, // via EqualityComparer.Default.Equals, we // only make one virtual call to EqualityComparer.IndexOf. return _size != 0 && IndexOf(item) != -1; } bool System.Collections.IList.Contains(Object item) { if (IsCompatibleObject(item)) { return Contains((T)item); } return false; } public UncheckedList ConvertAll(Converter converter) { UncheckedList list = new UncheckedList(_size); for (int i = 0; i < _size; i++) { list._items[i] = converter(_items[i]); } list._size = _size; return list; } // Copies this UncheckedList into array, which must be of a // compatible array type. // public void CopyTo(T[] array) { CopyTo(array, 0); } // Copies this UncheckedList into array, which must be of a // compatible array type. // void System.Collections.ICollection.CopyTo(Array array, int arrayIndex) { try { // Array.Copy will check for NULL. Array.Copy(_items, 0, array, arrayIndex, _size); } catch (ArrayTypeMismatchException) { } } // Copies a section of this list to the given array at the given index. // // The method uses the Array.Copy method to copy the elements. // public void CopyTo(int index, T[] array, int arrayIndex, int count) { // Delegate rest of error checking to Array.Copy. Array.Copy(_items, index, array, arrayIndex, count); } public void CopyTo(T[] array, int arrayIndex) { // Delegate rest of error checking to Array.Copy. Array.Copy(_items, 0, array, arrayIndex, _size); } // Ensures that the capacity of this list is at least the given minimum // value. If the current capacity of the list is less than min, the // capacity is increased to twice the current capacity or to min, // whichever is larger. private void EnsureCapacity(int min) { if (_items.Length < min) { int newCapacity = _items.Length == 0 ? _defaultCapacity : _items.Length * 2; // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow. // Note that this check works even when _items.Length overflowed thanks to the (uint) cast if ((uint) newCapacity > Int32.MaxValue) newCapacity = Int32.MaxValue; if (newCapacity < min) newCapacity = min; Capacity = newCapacity; } } public bool Exists(Predicate match) { return FindIndex(match) != -1; } public T Find(Predicate match) { for (int i = 0; i < _size; i++) { if (match(_items[i])) { return _items[i]; } } return default(T); } public UncheckedList FindAll(Predicate match) { UncheckedList list = new UncheckedList(); for (int i = 0; i < _size; i++) { if (match(_items[i])) { list.Add(_items[i]); } } return list; } public int FindIndex(Predicate match) { return FindIndex(0, _size, match); } public int FindIndex(int startIndex, Predicate match) { return FindIndex(startIndex, _size - startIndex, match); } public int FindIndex(int startIndex, int count, Predicate match) { int endIndex = startIndex + count; for (int i = startIndex; i < endIndex; i++) { if (match(_items[i])) return i; } return -1; } public T FindLast(Predicate match) { for (int i = _size - 1; i >= 0; i--) { if (match(_items[i])) { return _items[i]; } } return default(T); } public int FindLastIndex(Predicate match) { return FindLastIndex(_size - 1, _size, match); } public int FindLastIndex(int startIndex, Predicate match) { return FindLastIndex(startIndex, startIndex + 1, match); } public int FindLastIndex(int startIndex, int count, Predicate match) { int endIndex = startIndex - count; for (int i = startIndex; i > endIndex; i--) { if (match(_items[i])) { return i; } } return -1; } public void ForEach(Action action) { int version = _version; for (int i = 0; i < _size; i++) { if (version != _version) { break; } action(_items[i]); } } // Returns an enumerator for this list with the given // permission for removal of elements. If modifications made to the list // while an enumeration is in progress, the MoveNext and // GetObject methods of the enumerator will throw an exception. // public Enumerator GetEnumerator() { return new Enumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(this); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return new Enumerator(this); } public UncheckedList GetRange(int index, int count) { UncheckedList list = new UncheckedList(count); Array.Copy(_items, index, list._items, 0, count); list._size = count; return list; } // Returns the index of the first occurrence of a given value in a range of // this list. The list is searched forwards from beginning to end. // The elements of the list are compared to the given value using the // Object.Equals method. // // This method uses the Array.IndexOf method to perform the // search. // public int IndexOf(T item) { return Array.IndexOf(_items, item, 0, _size); } int System.Collections.IList.IndexOf(Object item) { if (IsCompatibleObject(item)) { return IndexOf((T)item); } return -1; } // Returns the index of the first occurrence of a given value in a range of // this list. The list is searched forwards, starting at index // index and ending at count number of elements. The // elements of the list are compared to the given value using the // Object.Equals method. // // This method uses the Array.IndexOf method to perform the // search. // public int IndexOf(T item, int index) { return Array.IndexOf(_items, item, index, _size - index); } // Returns the index of the first occurrence of a given value in a range of // this list. The list is searched forwards, starting at index // index and upto count number of elements. The // elements of the list are compared to the given value using the // Object.Equals method. // // This method uses the Array.IndexOf method to perform the // search. // public int IndexOf(T item, int index, int count) { return Array.IndexOf(_items, item, index, count); } // Inserts an element into this list at a given index. The size of the list // is increased by one. If required, the capacity of the list is doubled // before inserting the new element. // public void Insert(int index, T item) { if (_size == _items.Length) EnsureCapacity(_size + 1); if (index < _size) { Array.Copy(_items, index, _items, index + 1, _size - index); } _items[index] = item; _size++; _version++; } void System.Collections.IList.Insert(int index, Object item) { try { Insert(index, (T)item); } catch (InvalidCastException) { } } // Inserts the elements of the given collection at a given index. If // required, the capacity of the list is increased to twice the previous // capacity or the new size, whichever is larger. Ranges may be added // to the end of the list by setting index to the UncheckedList's size. // public void InsertRange(int index, IEnumerable collection) { ICollection c = collection as ICollection; if (c != null) { // if collection is ICollection int count = c.Count; if (count > 0) { EnsureCapacity(_size + count); if (index < _size) { Array.Copy(_items, index, _items, index + count, _size - index); } // If we're inserting a UncheckedList into itself, we want to be able to deal with that. if (this == c) { // Copy first part of _items to insert location Array.Copy(_items, 0, _items, index, index); // Copy last part of _items back to inserted location Array.Copy(_items, index + count, _items, index * 2, _size - index); } else { c.CopyTo(_items, index); } _size += count; } } else if (index < _size) { // We're inserting a lazy enumerable. Call Insert on each of the constituent items. using (IEnumerator en = collection.GetEnumerator()) { while (en.MoveNext()) { Insert(index++, en.Current); } } } else { // We're adding a lazy enumerable because the index is at the end of this list. AddEnumerable(collection); } _version++; } // Returns the index of the last occurrence of a given value in a range of // this list. The list is searched backwards, starting at the end // and ending at the first element in the list. The elements of the list // are compared to the given value using the Object.Equals method. // // This method uses the Array.LastIndexOf method to perform the // search. // public int LastIndexOf(T item) { if (_size == 0) { // Special case for empty list return -1; } else { return LastIndexOf(item, _size - 1, _size); } } // Returns the index of the last occurrence of a given value in a range of // this list. The list is searched backwards, starting at index // index and ending at the first element in the list. The // elements of the list are compared to the given value using the // Object.Equals method. // // This method uses the Array.LastIndexOf method to perform the // search. // public int LastIndexOf(T item, int index) { return LastIndexOf(item, index, index + 1); } // Returns the index of the last occurrence of a given value in a range of // this list. The list is searched backwards, starting at index // index and upto count elements. The elements of // the list are compared to the given value using the Object.Equals // method. // // This method uses the Array.LastIndexOf method to perform the // search. // public int LastIndexOf(T item, int index, int count) { if (_size == 0) { // Special case for empty list return -1; } return Array.LastIndexOf(_items, item, index, count); } // Removes the element at the given index. The size of the list is // decreased by one. // public bool Remove(T item) { int index = IndexOf(item); if (index >= 0) { RemoveAt(index); return true; } return false; } void System.Collections.IList.Remove(Object item) { if (IsCompatibleObject(item)) { Remove((T)item); } } // This method removes all items which matches the predicate. // The complexity is O(n). public int RemoveAll(Predicate match) { int freeIndex = 0; // the first free slot in items array // Find the first item which needs to be removed. while (freeIndex < _size && !match(_items[freeIndex])) freeIndex++; if (freeIndex >= _size) return 0; int current = freeIndex + 1; while (current < _size) { // Find the first item which needs to be kept. while (current < _size && match(_items[current])) current++; if (current < _size) { // copy item to the free slot. _items[freeIndex++] = _items[current++]; } } if (!typeof(T).IsValueType) { Array.Clear(_items, freeIndex, _size - freeIndex); // Clear the elements so that the gc can reclaim the references. } int result = _size - freeIndex; _size = freeIndex; _version++; return result; } // Removes the element at the given index. The size of the list is // decreased by one. // public void RemoveAt(int index) { _size--; if (index < _size) { Array.Copy(_items, index + 1, _items, index, _size - index); } if (!typeof(T).IsValueType) { _items[_size] = default(T); } _version++; } // Removes a range of elements from this list. // public void RemoveRange(int index, int count) { if (count > 0) { int i = _size; _size -= count; if (index < _size) { Array.Copy(_items, index + count, _items, index, _size - index); } _version++; if (!typeof(T).IsValueType) { Array.Clear(_items, _size, count); } } } // Reverses the elements in this list. public void Reverse() { Reverse(0, Count); } // Reverses the elements in a range of this list. Following a call to this // method, an element in the range given by index and count // which was previously located at index i will now be located at // index index + (index + count - i - 1). // public void Reverse(int index, int count) { if (count > 1) { Array.Reverse(_items, index, count); } _version++; } // Sorts the elements in this list. Uses the default comparer and // Array.Sort. public void Sort() { Sort(0, Count, null); } // Sorts the elements in this list. Uses Array.Sort with the // provided comparer. public void Sort(IComparer comparer) { Sort(0, Count, comparer); } // Sorts the elements in a section of this list. The sort compares the // elements to each other using the given IComparer interface. If // comparer is null, the elements are compared to each other using // the IComparable interface, which in that case must be implemented by all // elements of the list. // // This method uses the Array.Sort method to sort the elements. // public void Sort(int index, int count, IComparer comparer) { if (count > 1) { Array.Sort(_items, index, count, comparer); } _version++; } public void Sort(Comparison comparison) { throw new NotImplementedException(); /*if (_size > 1) { ArraySortHelper.Sort(_items, 0, _size, comparison); } _version++;*/ } // ToArray returns an array containing the contents of the UncheckedList. // This requires copying the UncheckedList, which is an O(n) operation. public T[] ToArray() { if (_size == 0) { return _emptyArray; } T[] array = new T[_size]; Array.Copy(_items, 0, array, 0, _size); return array; } // Sets the capacity of this list to the size of the list. This method can // be used to minimize a list's memory overhead once it is known that no // new elements will be added to the list. To completely clear a list and // release all memory referenced by the list, execute the following // statements: // // list.Clear(); // list.TrimExcess(); // public void TrimExcess() { int threshold = (int)(((double)_items.Length) * 0.9); if (_size < threshold) { Capacity = _size; } } public bool TrueForAll(Predicate match) { for (int i = 0; i < _size; i++) { if (!match(_items[i])) { return false; } } return true; } private void AddEnumerable(IEnumerable enumerable) { Debug.Assert(enumerable != null); Debug.Assert(!(enumerable is ICollection), "We should have optimized for this beforehand."); using (IEnumerator en = enumerable.GetEnumerator()) { _version++; // Even if the enumerable has no items, we can update _version. while (en.MoveNext()) { // Capture Current before doing anything else. If this throws // an exception, we want to make a clean break. T current = en.Current; if (_size == _items.Length) { EnsureCapacity(_size + 1); } _items[_size++] = current; } } } public struct Enumerator : IEnumerator, System.Collections.IEnumerator { private UncheckedList list; private int index; private int version; private T current; internal Enumerator(UncheckedList list) { this.list = list; index = 0; version = list._version; current = default(T); } public void Dispose() { } public bool MoveNext() { UncheckedList localUncheckedList = list; if (version == localUncheckedList._version && ((uint)index < (uint)localUncheckedList._size)) { current = localUncheckedList._items[index]; index++; return true; } return MoveNextRare(); } private bool MoveNextRare() { index = list._size + 1; current = default(T); return false; } public T Current { get { return current; } } Object System.Collections.IEnumerator.Current { get { return Current; } } void System.Collections.IEnumerator.Reset() { index = 0; current = default(T); } } } } ================================================ FILE: SGFUnity/ILRuntime/Reflection/Extensions.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using Mono.Cecil; using ILRuntime.CLR.Method; using ILRuntime.CLR.TypeSystem; namespace ILRuntime.Reflection { static class Extensions { public static object CreateInstance(this CustomAttribute attribute, IType at, Runtime.Enviorment.AppDomain appdomain) { object ins; List param = null; if (at is ILType) { var it = (ILType)at; if (!attribute.HasConstructorArguments) ins = it.Instantiate(true); else { ins = it.Instantiate(false); if (param == null) param = new List(); param.Clear(); object[] p = new object[attribute.ConstructorArguments.Count]; for (int j = 0; j < attribute.ConstructorArguments.Count; j++) { var ca = attribute.ConstructorArguments[j]; param.Add(appdomain.GetType(ca.Type, null, null)); p[j] = ca.Value; } var ctor = it.GetConstructor(param); appdomain.Invoke(ctor, ins, p); } if (attribute.HasProperties) { object[] p = new object[1]; foreach (var j in attribute.Properties) { p[0] = j.Argument.Value; var setter = it.GetMethod("set_" + j.Name, 1); appdomain.Invoke(setter, ins, p); } } } else { param = new List(); object[] p = null; if (attribute.HasConstructorArguments) { p = new object[attribute.ConstructorArguments.Count]; for (int j = 0; j < attribute.ConstructorArguments.Count; j++) { var ca = attribute.ConstructorArguments[j]; param.Add(appdomain.GetType(ca.Type, null, null)); p[j] = ca.Value; } } ins = ((CLRMethod)at.GetConstructor(param)).ConstructorInfo.Invoke(p); if (attribute.HasProperties) { foreach (var j in attribute.Properties) { var prop = at.TypeForCLR.GetProperty(j.Name); prop.SetValue(ins, j.Argument.Value, null); } } } return ins; } } } ================================================ FILE: SGFUnity/ILRuntime/Reflection/ILRuntimeConstructorInfo.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Globalization; using ILRuntime.CLR.Method; using ILRuntime.CLR.TypeSystem; namespace ILRuntime.Reflection { public class ILRuntimeConstructorInfo : ConstructorInfo { ILMethod method; ILRuntimeParameterInfo[] parameters; public ILRuntimeConstructorInfo(ILMethod m) { method = m; parameters = new ILRuntimeParameterInfo[m.ParameterCount]; for(int i = 0; i < m.ParameterCount; i++) { parameters[i] = new ILRuntimeParameterInfo(m.Parameters[i]); } } internal ILMethod ILMethod { get { return method; } } public override MethodAttributes Attributes { get { return MethodAttributes.Public; } } public override Type DeclaringType { get { return method.DeclearingType.ReflectionType; } } public override RuntimeMethodHandle MethodHandle { get { throw new NotImplementedException(); } } public override string Name { get { return method.Name; } } public override Type ReflectedType { get { return method.DeclearingType.ReflectionType; } } public override object[] GetCustomAttributes(bool inherit) { throw new NotImplementedException(); } public override object[] GetCustomAttributes(Type attributeType, bool inherit) { throw new NotImplementedException(); } public override MethodImplAttributes GetMethodImplementationFlags() { throw new NotImplementedException(); } public override ParameterInfo[] GetParameters() { return parameters; } public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) { var res = ((ILType)method.DeclearingType).Instantiate(false); method.DeclearingType.AppDomain.Invoke(method, res, parameters); return res; } public override bool IsDefined(Type attributeType, bool inherit) { throw new NotImplementedException(); } public override object Invoke(BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) { var res = ((ILType)method.DeclearingType).Instantiate(false); method.DeclearingType.AppDomain.Invoke(method, res, parameters); return res; } } } ================================================ FILE: SGFUnity/ILRuntime/Reflection/ILRuntimeFieldInfo.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Globalization; using Mono.Cecil; using ILRuntime.CLR.Utils; using ILRuntime.CLR.TypeSystem; using ILRuntime.Runtime; using ILRuntime.Runtime.Stack; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; namespace ILRuntime.Reflection { public class ILRuntimeFieldInfo : FieldInfo { System.Reflection.FieldAttributes attr; ILRuntimeType dType; ILType ilType; IType fieldType; bool isStatic; int fieldIdx; string name; FieldDefinition definition; Runtime.Enviorment.AppDomain appdomain; object[] customAttributes; Type[] attributeTypes; public IType ILFieldType { get { return fieldType; } } public ILRuntimeFieldInfo(FieldDefinition def, ILRuntimeType declaredType, bool isStatic, int fieldIdx) { definition = def; this.name = def.Name; dType = declaredType; ilType = dType.ILType; appdomain = ilType.AppDomain; this.isStatic = isStatic; this.fieldIdx = fieldIdx; if (isStatic) attr |= System.Reflection.FieldAttributes.Static; if (def.IsPublic) { attr |= System.Reflection.FieldAttributes.Public; } else attr |= System.Reflection.FieldAttributes.Private; fieldType = isStatic ? ilType.StaticFieldTypes[fieldIdx] : ilType.FieldTypes[fieldIdx]; } public ILRuntimeFieldInfo(FieldDefinition def, ILRuntimeType declaredType, int fieldIdx, IType fieldType) { definition = def; this.name = def.Name; dType = declaredType; ilType = dType.ILType; appdomain = ilType.AppDomain; this.isStatic = false; this.fieldIdx = fieldIdx; if (isStatic) attr |= System.Reflection.FieldAttributes.Static; if (def.IsPublic) { attr |= System.Reflection.FieldAttributes.Public; } else attr |= System.Reflection.FieldAttributes.Private; this.fieldType = fieldType; } void InitializeCustomAttribute() { customAttributes = new object[definition.CustomAttributes.Count]; attributeTypes = new Type[customAttributes.Length]; for (int i = 0; i < definition.CustomAttributes.Count; i++) { var attribute = definition.CustomAttributes[i]; var at = appdomain.GetType(attribute.AttributeType, null, null); try { object ins = attribute.CreateInstance(at, appdomain); attributeTypes[i] = at.ReflectionType; customAttributes[i] = ins; } catch { attributeTypes[i] = typeof(Attribute); } } } public override System.Reflection.FieldAttributes Attributes { get { return attr; } } public override Type DeclaringType { get { return dType; } } public override RuntimeFieldHandle FieldHandle { get { throw new NotImplementedException(); } } public override Type FieldType { get { return fieldType.ReflectionType; } } public override string Name { get { return name; } } public override Type ReflectedType { get { return fieldType.ReflectionType; } } public override object[] GetCustomAttributes(bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); return customAttributes; } public override object[] GetCustomAttributes(Type attributeType, bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); List res = new List(); for (int i = 0; i < customAttributes.Length; i++) { if (attributeTypes[i] == attributeType) res.Add(customAttributes[i]); } return res.ToArray(); } public override object GetValue(object obj) { unsafe { StackObject esp; ILTypeInstance ins; if (isStatic) { ins = ilType.StaticInstance; } else { if (obj is ILTypeInstance) ins = (ILTypeInstance)obj; else ins = ((CrossBindingAdaptorType)obj).ILInstance; } return fieldType.TypeForCLR.CheckCLRTypes(ins[fieldIdx]); } } public override bool IsDefined(Type attributeType, bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); for (int i = 0; i < customAttributes.Length; i++) { if (attributeTypes[i] == attributeType) return true; } return false; } public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture) { unsafe { StackObject esp; if (value is CrossBindingAdaptorType) value = ((CrossBindingAdaptorType)value).ILInstance; ILTypeInstance ins; if (isStatic) { ins = ilType.StaticInstance; } else { if (obj is ILTypeInstance) ins = (ILTypeInstance)obj; else ins = ((CrossBindingAdaptorType)obj).ILInstance; } ins[fieldIdx] = value; } } } } ================================================ FILE: SGFUnity/ILRuntime/Reflection/ILRuntimeMethodInfo.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Globalization; using ILRuntime.CLR.Method; namespace ILRuntime.Reflection { public class ILRuntimeMethodInfo : MethodInfo { ILMethod method; ILRuntimeParameterInfo[] parameters; Mono.Cecil.MethodDefinition definition; ILRuntime.Runtime.Enviorment.AppDomain appdomain; object[] customAttributes; Type[] attributeTypes; public ILRuntimeMethodInfo(ILMethod m) { method = m; definition = m.Definition; appdomain = m.DeclearingType.AppDomain; parameters = new ILRuntimeParameterInfo[m.ParameterCount]; for (int i = 0; i < m.ParameterCount; i++) { parameters[i] = new ILRuntimeParameterInfo(m.Parameters[i]); } } void InitializeCustomAttribute() { customAttributes = new object[definition.CustomAttributes.Count]; attributeTypes = new Type[customAttributes.Length]; for (int i = 0; i < definition.CustomAttributes.Count; i++) { var attribute = definition.CustomAttributes[i]; var at = appdomain.GetType(attribute.AttributeType, null, null); try { object ins = attribute.CreateInstance(at, appdomain); attributeTypes[i] = at.ReflectionType; customAttributes[i] = ins; } catch { attributeTypes[i] = typeof(Attribute); } } } internal ILMethod ILMethod { get { return method; } } public override MethodAttributes Attributes { get { return MethodAttributes.Public; } } public override Type DeclaringType { get { return method.DeclearingType.ReflectionType; } } public override RuntimeMethodHandle MethodHandle { get { throw new NotImplementedException(); } } public override string Name { get { return method.Name; } } public override Type ReflectedType { get { return method.DeclearingType.ReflectionType; } } public override ICustomAttributeProvider ReturnTypeCustomAttributes { get { throw new NotImplementedException(); } } public override MethodInfo GetBaseDefinition() { return this; } public override object[] GetCustomAttributes(bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); return customAttributes; } public override object[] GetCustomAttributes(Type attributeType, bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); List res = new List(); for (int i = 0; i < customAttributes.Length; i++) { if (attributeTypes[i] == attributeType) res.Add(customAttributes[i]); } return res.ToArray(); } public override MethodImplAttributes GetMethodImplementationFlags() { throw new NotImplementedException(); } public override ParameterInfo[] GetParameters() { throw new NotImplementedException(); } public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) { if (method.HasThis) { var res = appdomain.Invoke(method, obj, parameters); return res; } else return appdomain.Invoke(method, null, parameters); } public override bool IsDefined(Type attributeType, bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); for (int i = 0; i < customAttributes.Length; i++) { if (attributeTypes[i] == attributeType) return true; } return false; } } } ================================================ FILE: SGFUnity/ILRuntime/Reflection/ILRuntimeParameterInfo.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Globalization; using ILRuntime.CLR.TypeSystem; namespace ILRuntime.Reflection { public class ILRuntimeParameterInfo : ParameterInfo { IType type; public ILRuntimeParameterInfo(IType type) { this.type = type; } public override Type ParameterType { get { return type.ReflectionType; } } } } ================================================ FILE: SGFUnity/ILRuntime/Reflection/ILRuntimePropertyInfo.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Globalization; using ILRuntime.CLR.Method; using ILRuntime.CLR.TypeSystem; namespace ILRuntime.Reflection { public class ILRuntimePropertyInfo : PropertyInfo { ILMethod getter, setter; ILType dType; Mono.Cecil.PropertyDefinition definition; ILRuntime.Runtime.Enviorment.AppDomain appdomain; object[] customAttributes; Type[] attributeTypes; static object[] param = new object[1]; public ILMethod Getter { get { return getter; } set { getter = value; } } public ILMethod Setter { get { return setter; } set { setter = value; } } public bool IsPublic { get { if (getter != null) return getter.Definition.IsPublic; else return setter.Definition.IsPublic; } } public bool IsStatic { get { if (getter != null) return getter.IsStatic; else return setter.IsStatic; } } public ILRuntimePropertyInfo(Mono.Cecil.PropertyDefinition definition, ILType dType) { this.definition = definition; this.dType = dType; appdomain = dType.AppDomain; } void InitializeCustomAttribute() { customAttributes = new object[definition.CustomAttributes.Count]; attributeTypes = new Type[customAttributes.Length]; for (int i = 0; i < definition.CustomAttributes.Count; i++) { var attribute = definition.CustomAttributes[i]; var at = appdomain.GetType(attribute.AttributeType, null, null); try { object ins = attribute.CreateInstance(at, appdomain); attributeTypes[i] = at.ReflectionType; customAttributes[i] = ins; } catch { attributeTypes[i] = typeof(Attribute); } } } public override string Name { get { return definition.Name; } } public override Type ReflectedType { get { return dType.ReflectionType; } } public override PropertyAttributes Attributes { get { return PropertyAttributes.None; } } public override bool CanRead { get { return getter != null; } } public override bool CanWrite { get { return setter != null; } } public override Type PropertyType { get { if (getter != null) return getter.ReturnType.ReflectionType; else { return setter.Parameters[0].ReflectionType; } } } public override Type DeclaringType { get { return dType.ReflectionType; } } public override object[] GetCustomAttributes(bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); return customAttributes; } public override object[] GetCustomAttributes(Type attributeType, bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); List res = new List(); for (int i = 0; i < customAttributes.Length; i++) { if (attributeTypes[i] == attributeType) res.Add(customAttributes[i]); } return res.ToArray(); } public override bool IsDefined(Type attributeType, bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); for (int i = 0; i < customAttributes.Length; i++) { if (attributeTypes[i] == attributeType) return true; } return false; } public override MethodInfo[] GetAccessors(bool nonPublic) { throw new NotImplementedException(); } public override MethodInfo GetGetMethod(bool nonPublic) { if (getter != null) return getter.ReflectionMethodInfo; return null; } public override ParameterInfo[] GetIndexParameters() { throw new NotImplementedException(); } public override MethodInfo GetSetMethod(bool nonPublic) { if (setter != null) return setter.ReflectionMethodInfo; return null; } public override object GetValue(object obj, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture) { return appdomain.Invoke(getter, obj, null); } public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture) { param[0] = value; appdomain.Invoke(setter, obj, param); } } } ================================================ FILE: SGFUnity/ILRuntime/Reflection/ILRuntimeType.cs ================================================ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection; using System.Text; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Intepreter; namespace ILRuntime.Reflection { public class ILRuntimeType : Type { ILType type; Runtime.Enviorment.AppDomain appdomain; object[] customAttributes; Type[] attributeTypes; ILRuntimeFieldInfo[] fields; ILRuntimePropertyInfo[] properties; ILRuntimeMethodInfo[] methods; public ILType ILType { get { return type; } } public ILRuntimeType(ILType t) { type = t; appdomain = t.AppDomain; } void InitializeCustomAttribute() { customAttributes = new object[type.TypeDefinition.CustomAttributes.Count]; attributeTypes = new Type[customAttributes.Length]; for (int i = 0; i < type.TypeDefinition.CustomAttributes.Count; i++) { var attribute = type.TypeDefinition.CustomAttributes[i]; var at = appdomain.GetType(attribute.AttributeType, type, null); try { object ins = attribute.CreateInstance(at, appdomain); attributeTypes[i] = at.ReflectionType is ILRuntimeWrapperType ? at.TypeForCLR : at.ReflectionType; customAttributes[i] = ins; } catch { attributeTypes[i] = typeof(Attribute); } } } void InitializeProperties() { int cnt = type.TypeDefinition.HasProperties ? type.TypeDefinition.Properties.Count : 0; properties = new ILRuntimePropertyInfo[cnt]; for (int i = 0; i < cnt; i++) { Mono.Cecil.PropertyDefinition pd = type.TypeDefinition.Properties[i]; ILRuntimePropertyInfo pi = new ILRuntimePropertyInfo(pd, type); properties[i] = pi; if (pd.GetMethod != null) pi.Getter = type.GetMethod(pd.GetMethod.Name, 0) as ILMethod; if (pd.SetMethod != null) pi.Setter = type.GetMethod(pd.SetMethod.Name, 1) as ILMethod; } } void InitializeMethods() { var methods = type.GetMethods(); this.methods = new ILRuntimeMethodInfo[methods.Count]; for(int i = 0; i < methods.Count; i++) { this.methods[i] = (ILRuntimeMethodInfo)((ILMethod)methods[i]).ReflectionMethodInfo; } } void InitializeFields() { int staticCnt = type.StaticFieldTypes != null ? type.StaticFieldTypes.Length : 0; fields = new ILRuntimeFieldInfo[type.TotalFieldCount + staticCnt]; for (int i = 0; i < type.TotalFieldCount; i++) { Mono.Cecil.FieldDefinition fd; var t = type.GetField(i, out fd); fields[i] = new ILRuntimeFieldInfo(fd, this, i, t); } for (int i = type.TotalFieldCount; i < type.TotalFieldCount + staticCnt; i++) { fields[i] = new ILRuntimeFieldInfo(type.StaticFieldDefinitions[i - type.TotalFieldCount], this, true, i - type.TotalFieldCount); } } public override Assembly Assembly { get { return typeof(ILRuntimeType).Assembly; } } public override string AssemblyQualifiedName { get { return type.FullName; } } public override Type BaseType { get { return type.BaseType != null ? type.BaseType.ReflectionType : null; } } public override string FullName { get { return type.FullName; } } public override Guid GUID { get { throw new NotImplementedException(); } } public override Module Module { get { throw new NotImplementedException(); } } public override string Name { get { return type.Name; } } public override string Namespace { get { throw new NotImplementedException(); } } public override Type UnderlyingSystemType { get { return typeof(ILTypeInstance); } } public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) { var ctors = type.GetConstructors(); ConstructorInfo[] res = new ConstructorInfo[ctors.Count]; for(int i = 0; i < res.Length; i++) { res[i] = ctors[i].ReflectionConstructorInfo; } return res; } public override object[] GetCustomAttributes(bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); return customAttributes; } public override object[] GetCustomAttributes(Type attributeType, bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); List res = new List(); for(int i = 0; i < customAttributes.Length; i++) { if (attributeTypes[i] == attributeType) res.Add(customAttributes[i]); } return res.ToArray(); } public override Type GetElementType() { if (type.IsArray) { return type.ElementType.ReflectionType; } else throw new NotImplementedException(); } public override EventInfo GetEvent(string name, BindingFlags bindingAttr) { throw new NotImplementedException(); } public override EventInfo[] GetEvents(BindingFlags bindingAttr) { throw new NotImplementedException(); } public override FieldInfo GetField(string name, BindingFlags bindingAttr) { if (fields == null) InitializeFields(); foreach(var i in fields) { if (i.Name == name) return i; } return null; } public override FieldInfo[] GetFields(BindingFlags bindingAttr) { if (fields == null) InitializeFields(); bool isPublic = (bindingAttr & BindingFlags.Public) == BindingFlags.Public; bool isPrivate = (bindingAttr & BindingFlags.NonPublic) == BindingFlags.NonPublic; bool isStatic = (bindingAttr & BindingFlags.Static) == BindingFlags.Static; bool isInstance = (bindingAttr & BindingFlags.Instance) == BindingFlags.Instance; List res = new List(); foreach(var i in fields) { if (isPublic != i.IsPublic && isPrivate != !i.IsPublic) continue; if ((isStatic != i.IsStatic) && (isInstance != !i.IsStatic)) continue; res.Add(i); } return res.ToArray(); } public override Type GetInterface(string name, bool ignoreCase) { if (type.FirstCLRInterface != null) { if (type.FirstCLRInterface.Name == name) return type.FirstCLRInterface.TypeForCLR; else return null; } else return null; } public override Type[] GetInterfaces() { if (type.FirstCLRInterface != null) return new Type[] { type.FirstCLRInterface.TypeForCLR }; else return new Type[0]; } public override MemberInfo[] GetMembers(BindingFlags bindingAttr) { if (methods == null) InitializeMethods(); if (fields == null) InitializeFields(); if (properties == null) InitializeProperties(); MemberInfo[] res = new MemberInfo[methods.Length + fields.Length + properties.Length]; for (int i = 0; i < methods.Length; i++) { res[i] = methods[i]; } for (int i = methods.Length; i < methods.Length + fields.Length; i++) { res[i] = fields[i - methods.Length]; } for (int i = methods.Length + fields.Length; i < res.Length; i++) { res[i] = properties[i- methods.Length - fields.Length]; } return res; } public override MethodInfo[] GetMethods(BindingFlags bindingAttr) { if (methods == null) InitializeMethods(); return methods; } public override Type GetNestedType(string name, BindingFlags bindingAttr) { throw new NotImplementedException(); } public override Type[] GetNestedTypes(BindingFlags bindingAttr) { throw new NotImplementedException(); } public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) { if (properties == null) InitializeProperties(); bool isPublic = (bindingAttr & BindingFlags.Public) == BindingFlags.Public; bool isPrivate = (bindingAttr & BindingFlags.NonPublic) == BindingFlags.NonPublic; bool isStatic = (bindingAttr & BindingFlags.Static) == BindingFlags.Static; bool isInstance = (bindingAttr & BindingFlags.Instance) == BindingFlags.Instance; List res = new List(); foreach (var i in properties) { if (isPublic != i.IsPublic && isPrivate != !i.IsPublic) continue; if ((isStatic != i.IsStatic) && (isInstance != !i.IsStatic)) continue; res.Add(i); } return res.ToArray(); } public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters) { throw new NotImplementedException(); } public override bool IsDefined(Type attributeType, bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); for (int i = 0; i < customAttributes.Length; i++) { if (attributeTypes[i] == attributeType) return true; } return false; } protected override TypeAttributes GetAttributeFlagsImpl() { TypeAttributes res = TypeAttributes.Public; if (type.TypeDefinition.IsAbstract) res |= TypeAttributes.Abstract; if (!type.IsValueType) res |= TypeAttributes.Class; if (type.TypeDefinition.IsSealed) res |= TypeAttributes.Sealed; return res; } protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) { List param = new List(); for (int i = 0; i < types.Length; i++) { if (types[i] is ILRuntimeType) param.Add(((ILRuntimeType)types[i]).type); else { var t = appdomain.GetType(types[i]); if (t == null) t = appdomain.GetType(types[i].AssemblyQualifiedName); if (t == null) throw new TypeLoadException(); param.Add(t); } } var res = type.GetConstructor(param); if (res != null) return ((ILMethod)res).ReflectionConstructorInfo; else return null; } protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) { IMethod res; if (types == null) res = type.GetMethod(name); else { List param = new List(); for (int i = 0; i < types.Length; i++) { if (types[i] is ILRuntimeType) param.Add(((ILRuntimeType)types[i]).type); else { var t = appdomain.GetType(types[i]); if (t == null) t = appdomain.GetType(types[i].AssemblyQualifiedName); if (t == null) throw new TypeLoadException(); param.Add(t); } } bool declearedOnly = (bindingAttr & BindingFlags.DeclaredOnly) == BindingFlags.DeclaredOnly; res = type.GetMethod(name, param, null, null, declearedOnly); } if (res != null) return ((ILMethod)res).ReflectionMethodInfo; else return null; } protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) { if (properties == null) InitializeProperties(); foreach(var i in properties) { if (i.Name == name) return i; } return null; } protected override bool HasElementTypeImpl() { return false; } protected override bool IsArrayImpl() { return type.IsArray; } protected override bool IsByRefImpl() { return false; } protected override bool IsCOMObjectImpl() { return false; } protected override bool IsPointerImpl() { return false; } protected override bool IsPrimitiveImpl() { return false; } public override int GetHashCode() { return type.GetHashCode(); } public override bool Equals(object o) { return o is ILRuntimeType ? ((ILRuntimeType)o).type == type : false; } public override bool IsGenericType { get { return type.HasGenericParameter; } } public override bool IsGenericTypeDefinition { get { return type.HasGenericParameter; } } } } ================================================ FILE: SGFUnity/ILRuntime/Reflection/ILRuntimeWrapperType.cs ================================================ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection; using System.Text; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Intepreter; namespace ILRuntime.Reflection { public class ILRuntimeWrapperType : Type { CLRType type; Type et; public CLRType CLRType { get { return type; } } public Type RealType { get { return et; } } public override Guid GUID { get { return et.GUID; } } public override Module Module { get { return et.Module; } } public override Assembly Assembly { get { return et.Assembly; } } public override string FullName { get { return et.FullName; } } public override string Namespace { get { return et.Namespace; } } public override string AssemblyQualifiedName { get { return et.AssemblyQualifiedName; } } public override Type BaseType { get { return et.BaseType; } } public override Type UnderlyingSystemType { get { return et.UnderlyingSystemType; } } public override string Name { get { return et.Name; } } public ILRuntimeWrapperType(CLRType t) { type = t; et = t.TypeForCLR; } public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters) { return et.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters); } protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) { return et.GetConstructor(bindingAttr, binder, callConvention, types, modifiers); } public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) { return et.GetConstructors(bindingAttr); } protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) { return et.GetMethod(name, bindingAttr, binder, callConvention, types, modifiers); } public override MethodInfo[] GetMethods(BindingFlags bindingAttr) { return et.GetMethods(bindingAttr); } public override FieldInfo GetField(string name, BindingFlags bindingAttr) { return et.GetField(name, bindingAttr); } public override FieldInfo[] GetFields(BindingFlags bindingAttr) { return et.GetFields(bindingAttr); } public override Type GetInterface(string name, bool ignoreCase) { return et.GetInterface(name, ignoreCase); } public override Type[] GetInterfaces() { return et.GetInterfaces(); } public override EventInfo GetEvent(string name, BindingFlags bindingAttr) { return et.GetEvent(name, bindingAttr); } public override EventInfo[] GetEvents(BindingFlags bindingAttr) { return et.GetEvents(bindingAttr); } protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) { return et.GetProperty(name, bindingAttr, binder, returnType, types, modifiers); } public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) { return et.GetProperties(bindingAttr); } public override Type[] GetNestedTypes(BindingFlags bindingAttr) { return et.GetNestedTypes(bindingAttr); } public override int GetHashCode() { return type.GetHashCode(); } public override Type GetNestedType(string name, BindingFlags bindingAttr) { return et.GetNestedType(name, bindingAttr); } public override MemberInfo[] GetMembers(BindingFlags bindingAttr) { return et.GetMembers(bindingAttr); } protected override TypeAttributes GetAttributeFlagsImpl() { return et.Attributes; } protected override bool IsArrayImpl() { return et.IsArray; } protected override bool IsByRefImpl() { return et.IsByRef; } protected override bool IsPointerImpl() { return et.IsPointer; } protected override bool IsPrimitiveImpl() { return et.IsPrimitive; } protected override bool IsCOMObjectImpl() { return et.IsCOMObject; } public override Type GetElementType() { return et.GetElementType(); } protected override bool HasElementTypeImpl() { return et.HasElementType; } public override object[] GetCustomAttributes(bool inherit) { return et.GetCustomAttributes(inherit); } public override object[] GetCustomAttributes(Type attributeType, bool inherit) { return et.GetCustomAttributes(attributeType, inherit); } public override bool IsDefined(Type attributeType, bool inherit) { return et.IsDefined(attributeType, inherit); } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Adaptors/CLRCrossBindingAdaptors.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; namespace ILRuntime.Runtime.Adaptors { class AttributeAdaptor : CrossBindingAdaptor { public override Type AdaptorType { get { return typeof(Adaptor); } } public override Type BaseCLRType { get { return typeof(Attribute); } } public override object CreateCLRInstance(Enviorment.AppDomain appdomain, ILTypeInstance instance) { return new Adaptor(appdomain, instance); } class Adaptor : Attribute, CrossBindingAdaptorType { ILTypeInstance instance; ILRuntime.Runtime.Enviorment.AppDomain appdomain; bool isToStringGot; IMethod toString; public Adaptor(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance) { this.appdomain = appdomain; this.instance = instance; } public ILTypeInstance ILInstance { get { return instance; } } public override string ToString() { if (!isToStringGot) { isToStringGot = true; IMethod m = appdomain.ObjectType.GetMethod("ToString", 0); toString = instance.Type.GetVirtualMethod(m); } if (toString == null || toString is ILMethod) { return instance.ToString(); } else return instance.Type.FullName; } } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/CLRBinding/BindingCodeGenerator.cs ================================================ using System; using System.Collections.Generic; using System.Reflection; using System.Linq; using System.Text; using ILRuntime.Runtime.Enviorment; using ILRuntime.Other; namespace ILRuntime.Runtime.CLRBinding { public class BindingCodeGenerator { public static void GenerateBindingCode(List types, string outputPath, HashSet excludeMethods = null, HashSet excludeFields = null) { if (!System.IO.Directory.Exists(outputPath)) System.IO.Directory.CreateDirectory(outputPath); string[] oldFiles = System.IO.Directory.GetFiles(outputPath, "*.cs"); foreach (var i in oldFiles) { System.IO.File.Delete(i); } List clsNames = new List(); foreach (var i in types) { string clsName, realClsName; bool isByRef; if (i.GetCustomAttributes(typeof(ObsoleteAttribute), true).Length > 0) continue; i.GetClassName(out clsName, out realClsName, out isByRef); clsNames.Add(clsName); using (System.IO.StreamWriter sw = new System.IO.StreamWriter(outputPath + "/" + clsName + ".cs", false, Encoding.UTF8)) { sw.Write(@"using System; using System.Collections.Generic; using System.Reflection; using System.Runtime.InteropServices; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Stack; using ILRuntime.Reflection; using ILRuntime.CLR.Utils; namespace ILRuntime.Runtime.Generated { unsafe class "); sw.WriteLine(clsName); sw.Write(@" { public static void Register(ILRuntime.Runtime.Enviorment.AppDomain app) { BindingFlags flag = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; MethodBase method; FieldInfo field; Type[] args; Type type = typeof("); sw.Write(realClsName); sw.WriteLine(");"); MethodInfo[] methods = i.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly); FieldInfo[] fields = i.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly); string registerMethodCode = i.GenerateMethodRegisterCode(methods, excludeMethods); string registerFieldCode = i.GenerateFieldRegisterCode(fields, excludeFields); string registerValueTypeCode = i.GenerateValueTypeRegisterCode(realClsName); string registerMiscCode = i.GenerateMiscRegisterCode(realClsName, true, true); string commonCode = i.GenerateCommonCode(realClsName); ConstructorInfo[] ctors = i.GetConstructors(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly); string ctorRegisterCode = i.GenerateConstructorRegisterCode(ctors, excludeMethods); string methodWraperCode = i.GenerateMethodWraperCode(methods, realClsName, excludeMethods); string fieldWraperCode = i.GenerateFieldWraperCode(fields, realClsName, excludeFields); string cloneWraperCode = i.GenerateCloneWraperCode(fields, realClsName); string ctorWraperCode = i.GenerateConstructorWraperCode(ctors, realClsName, excludeMethods); sw.WriteLine(registerMethodCode); sw.WriteLine(registerFieldCode); sw.WriteLine(registerValueTypeCode); sw.WriteLine(registerMiscCode); sw.WriteLine(ctorRegisterCode); sw.WriteLine(" }"); sw.WriteLine(); sw.WriteLine(commonCode); sw.WriteLine(methodWraperCode); sw.WriteLine(fieldWraperCode); sw.WriteLine(cloneWraperCode); sw.WriteLine(ctorWraperCode); sw.WriteLine(" }"); sw.WriteLine("}"); sw.Flush(); } } using (System.IO.StreamWriter sw = new System.IO.StreamWriter(outputPath + "/CLRBindings.cs", false, Encoding.UTF8)) { sw.WriteLine(@"using System; using System.Collections.Generic; using System.Reflection; namespace ILRuntime.Runtime.Generated { class CLRBindings { /// /// Initialize the CLR binding, please invoke this AFTER CLR Redirection registration /// public static void Initialize(ILRuntime.Runtime.Enviorment.AppDomain app) {"); foreach (var i in clsNames) { sw.Write(" "); sw.Write(i); sw.WriteLine(".Register(app);"); } sw.WriteLine(@" } } }"); } } class CLRBindingGenerateInfo { public Type Type { get; set; } public HashSet Methods { get; set; } public HashSet Fields { get; set; } public HashSet Constructors { get; set; } public bool ArrayNeeded { get; set; } public bool DefaultInstanceNeeded { get; set; } public bool ValueTypeNeeded { get; set; } public bool NeedGenerate { get { if (Methods.Count == 0 && Constructors.Count == 0 && Fields.Count == 0 && !ArrayNeeded && !DefaultInstanceNeeded && !ValueTypeNeeded) return false; else { //Making CLRBinding for such types makes no sense if (Type == typeof(Delegate) || Type == typeof(System.Runtime.CompilerServices.RuntimeHelpers)) return false; return true; } } } } public static void GenerateBindingCode(ILRuntime.Runtime.Enviorment.AppDomain domain, string outputPath) { if (domain == null) return; if (!System.IO.Directory.Exists(outputPath)) System.IO.Directory.CreateDirectory(outputPath); Dictionary infos = new Dictionary(new ByReferenceKeyComparer()); CrawlAppdomain(domain, infos); string[] oldFiles = System.IO.Directory.GetFiles(outputPath, "*.cs"); foreach (var i in oldFiles) { System.IO.File.Delete(i); } HashSet excludeMethods = null; HashSet excludeFields = null; List clsNames = new List(); foreach (var info in infos) { if (!info.Value.NeedGenerate) continue; Type i = info.Value.Type; string clsName, realClsName; bool isByRef; if (i.GetCustomAttributes(typeof(ObsoleteAttribute), true).Length > 0) continue; i.GetClassName(out clsName, out realClsName, out isByRef); clsNames.Add(clsName); using (System.IO.StreamWriter sw = new System.IO.StreamWriter(outputPath + "/" + clsName + ".cs", false, Encoding.UTF8)) { sw.Write(@"using System; using System.Collections.Generic; using System.Reflection; using System.Runtime.InteropServices; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Stack; using ILRuntime.Reflection; using ILRuntime.CLR.Utils; namespace ILRuntime.Runtime.Generated { unsafe class "); sw.WriteLine(clsName); sw.Write(@" { public static void Register(ILRuntime.Runtime.Enviorment.AppDomain app) { BindingFlags flag = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; MethodBase method; FieldInfo field; Type[] args; Type type = typeof("); sw.Write(realClsName); sw.WriteLine(");"); MethodInfo[] methods = info.Value.Methods.ToArray(); FieldInfo[] fields = info.Value.Fields.ToArray(); string registerMethodCode = i.GenerateMethodRegisterCode(methods, excludeMethods); string registerFieldCode = fields.Length > 0 ? i.GenerateFieldRegisterCode(fields, excludeFields) : null; string registerValueTypeCode = info.Value.ValueTypeNeeded ? i.GenerateValueTypeRegisterCode(realClsName) : null; string registerMiscCode = i.GenerateMiscRegisterCode(realClsName, info.Value.DefaultInstanceNeeded, info.Value.ArrayNeeded); string commonCode = i.GenerateCommonCode(realClsName); ConstructorInfo[] ctors = info.Value.Constructors.ToArray(); string ctorRegisterCode = i.GenerateConstructorRegisterCode(ctors, excludeMethods); string methodWraperCode = i.GenerateMethodWraperCode(methods, realClsName, excludeMethods); string fieldWraperCode = fields.Length > 0 ? i.GenerateFieldWraperCode(fields, realClsName, excludeFields) : null; string cloneWraperCode = null; if (info.Value.ValueTypeNeeded) { //Memberwise clone should copy all fields var fs = i.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly); cloneWraperCode = i.GenerateCloneWraperCode(fs, realClsName); } string ctorWraperCode = i.GenerateConstructorWraperCode(ctors, realClsName, excludeMethods); sw.WriteLine(registerMethodCode); if (fields.Length > 0) sw.WriteLine(registerFieldCode); if (info.Value.ValueTypeNeeded) sw.WriteLine(registerValueTypeCode); if (!string.IsNullOrEmpty(registerMiscCode)) sw.WriteLine(registerMiscCode); sw.WriteLine(ctorRegisterCode); sw.WriteLine(" }"); sw.WriteLine(); sw.WriteLine(commonCode); sw.WriteLine(methodWraperCode); if (fields.Length > 0) sw.WriteLine(fieldWraperCode); if (info.Value.ValueTypeNeeded) sw.WriteLine(cloneWraperCode); sw.WriteLine(ctorWraperCode); sw.WriteLine(" }"); sw.WriteLine("}"); sw.Flush(); } } using (System.IO.StreamWriter sw = new System.IO.StreamWriter(outputPath + "/CLRBindings.cs", false, Encoding.UTF8)) { sw.WriteLine(@"using System; using System.Collections.Generic; using System.Reflection; namespace ILRuntime.Runtime.Generated { class CLRBindings { /// /// Initialize the CLR binding, please invoke this AFTER CLR Redirection registration /// public static void Initialize(ILRuntime.Runtime.Enviorment.AppDomain app) {"); foreach (var i in clsNames) { sw.Write(" "); sw.Write(i); sw.WriteLine(".Register(app);"); } sw.WriteLine(@" } } }"); } } static void CrawlAppdomain(ILRuntime.Runtime.Enviorment.AppDomain domain, Dictionary infos) { var arr = domain.LoadedTypes.Values.ToArray(); //Prewarm foreach (var type in arr) { if (type is CLR.TypeSystem.ILType) { if (type.HasGenericParameter) continue; var methods = type.GetMethods().ToList(); foreach (var i in ((CLR.TypeSystem.ILType)type).GetConstructors()) methods.Add(i); if (((CLR.TypeSystem.ILType)type).GetStaticConstroctor() != null) methods.Add(((CLR.TypeSystem.ILType)type).GetStaticConstroctor()); foreach (var j in methods) { CLR.Method.ILMethod method = j as CLR.Method.ILMethod; if (method != null) { if (method.GenericParameterCount > 0 && !method.IsGenericInstance) continue; var body = method.Body; } } } } arr = domain.LoadedTypes.Values.ToArray(); foreach (var type in arr) { if (type is CLR.TypeSystem.ILType) { if (type.HasGenericParameter) continue; var methods = type.GetMethods().ToList(); foreach (var i in ((CLR.TypeSystem.ILType)type).GetConstructors()) methods.Add(i); foreach (var j in methods) { CLR.Method.ILMethod method = j as CLR.Method.ILMethod; if (method != null) { if (method.GenericParameterCount > 0 && !method.IsGenericInstance) continue; var body = method.Body; foreach (var ins in body) { switch (ins.Code) { case Intepreter.OpCodes.OpCodeEnum.Newobj: { CLR.Method.CLRMethod m = domain.GetMethod(ins.TokenInteger) as CLR.Method.CLRMethod; if (m != null) { if (m.DeclearingType.IsDelegate) continue; Type t = m.DeclearingType.TypeForCLR; CLRBindingGenerateInfo info; if (!infos.TryGetValue(t, out info)) { info = CreateNewBindingInfo(t); infos[t] = info; } if (m.IsConstructor) info.Constructors.Add(m.ConstructorInfo); else info.Methods.Add(m.MethodInfo); } } break; case Intepreter.OpCodes.OpCodeEnum.Ldfld: case Intepreter.OpCodes.OpCodeEnum.Stfld: case Intepreter.OpCodes.OpCodeEnum.Ldflda: case Intepreter.OpCodes.OpCodeEnum.Ldsfld: case Intepreter.OpCodes.OpCodeEnum.Ldsflda: case Intepreter.OpCodes.OpCodeEnum.Stsfld: { var t = domain.GetType((int)(ins.TokenLong >> 32)) as CLR.TypeSystem.CLRType; if(t != null) { var fi = t.GetField((int)ins.TokenLong); if (fi != null && fi.IsPublic) { CLRBindingGenerateInfo info; if (!infos.TryGetValue(t.TypeForCLR, out info)) { info = CreateNewBindingInfo(t.TypeForCLR); infos[t.TypeForCLR] = info; } if(ins.Code == Intepreter.OpCodes.OpCodeEnum.Stfld || ins.Code == Intepreter.OpCodes.OpCodeEnum.Stsfld) { if (t.IsValueType) { info.ValueTypeNeeded = true; info.DefaultInstanceNeeded = true; } } if (t.TypeForCLR.CheckCanPinn() || !t.IsValueType) info.Fields.Add(fi); } } } break; case Intepreter.OpCodes.OpCodeEnum.Ldtoken: { if (ins.TokenInteger == 0) { var t = domain.GetType((int)(ins.TokenLong >> 32)) as CLR.TypeSystem.CLRType; if (t != null) { var fi = t.GetField((int)ins.TokenLong); if (fi != null) { CLRBindingGenerateInfo info; if (!infos.TryGetValue(t.TypeForCLR, out info)) { info = CreateNewBindingInfo(t.TypeForCLR); infos[t.TypeForCLR] = info; } info.Fields.Add(fi); } } } } break; case Intepreter.OpCodes.OpCodeEnum.Newarr: { var t = domain.GetType(ins.TokenInteger) as CLR.TypeSystem.CLRType; if(t != null) { CLRBindingGenerateInfo info; if (!infos.TryGetValue(t.TypeForCLR, out info)) { info = CreateNewBindingInfo(t.TypeForCLR); infos[t.TypeForCLR] = info; } info.ArrayNeeded = true; } } break; case Intepreter.OpCodes.OpCodeEnum.Call: case Intepreter.OpCodes.OpCodeEnum.Callvirt: { CLR.Method.CLRMethod m = domain.GetMethod(ins.TokenInteger) as CLR.Method.CLRMethod; if (m != null) { //Cannot explicit call base class's constructor directly if (m.IsConstructor) continue; if (!m.MethodInfo.IsPublic) continue; Type t = m.DeclearingType.TypeForCLR; CLRBindingGenerateInfo info; if (!infos.TryGetValue(t, out info)) { info = CreateNewBindingInfo(t); infos[t] = info; } info.Methods.Add(m.MethodInfo); } } break; } } } } } } } static CLRBindingGenerateInfo CreateNewBindingInfo(Type t) { CLRBindingGenerateInfo info = new CLRBindingGenerateInfo(); info.Type = t; info.Methods = new HashSet(); info.Fields = new HashSet(); info.Constructors = new HashSet(); return info; } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/CLRBinding/BindingGeneratorExtensions.cs ================================================ using System; using System.Collections.Generic; using System.Reflection; using System.Linq; using System.Text; using ILRuntime.Runtime.Enviorment; namespace ILRuntime.Runtime.CLRBinding { static class BindingGeneratorExtensions { internal static bool ShouldSkipField(this Type type, FieldInfo i) { if (i.IsPrivate) return true; //EventHandler is currently not supported if (i.IsSpecialName) { return true; } if (i.GetCustomAttributes(typeof(ObsoleteAttribute), true).Length > 0) return true; return false; } internal static bool ShouldSkipMethod(this Type type, MethodBase i) { if (i.IsPrivate) return true; if (i.IsGenericMethod) return true; //EventHandler is currently not supported var param = i.GetParameters(); if (i.IsSpecialName) { string[] t = i.Name.Split('_'); if (t[0] == "add" || t[0] == "remove") return true; if (t[0] == "get" || t[0] == "set") { Type[] ts; if (t[1] == "Item") { var cnt = t[0] == "set" ? param.Length - 1 : param.Length; ts = new Type[cnt]; for (int j = 0; j < cnt; j++) { ts[j] = param[j].ParameterType; } } else ts = new Type[0]; var prop = type.GetProperty(t[1], ts); if (prop == null) { return true; } if (prop.GetCustomAttributes(typeof(ObsoleteAttribute), true).Length > 0) return true; } } if (i.GetCustomAttributes(typeof(ObsoleteAttribute), true).Length > 0) return true; foreach (var j in param) { if (j.ParameterType.IsPointer) return true; } return false; } internal static void AppendParameters(this ParameterInfo[] param, StringBuilder sb) { bool first = true; foreach (var j in param) { if (first) first = false; else sb.Append(", "); if (j.IsOut && j.ParameterType.IsByRef) sb.Append("out "); else if (j.ParameterType.IsByRef) sb.Append("ref "); sb.Append(j.Name); } } internal static string GetRetrieveValueCode(this Type type, string realClsName) { if (type.IsByRef) type = type.GetElementType(); if (type.IsPrimitive) { if (type == typeof(int)) { return "ptr_of_this_method->Value"; } else if (type == typeof(long)) { return "*(long*)&ptr_of_this_method->Value"; } else if (type == typeof(short)) { return "(short)ptr_of_this_method->Value"; } else if (type == typeof(bool)) { return "ptr_of_this_method->Value == 1"; } else if (type == typeof(ushort)) { return "(ushort)ptr_of_this_method->Value"; } else if (type == typeof(float)) { return "*(float*)&ptr_of_this_method->Value"; } else if (type == typeof(double)) { return "*(double*)&ptr_of_this_method->Value"; } else if (type == typeof(byte)) { return "(byte)ptr_of_this_method->Value"; } else if (type == typeof(sbyte)) { return "(sbyte)ptr_of_this_method->Value"; } else if (type == typeof(uint)) { return "(uint)ptr_of_this_method->Value"; } else if (type == typeof(char)) { return "(char)ptr_of_this_method->Value"; } else if (type == typeof(ulong)) { return "*(ulong*)&ptr_of_this_method->Value"; } else throw new NotImplementedException(); } else { return string.Format("({0})typeof({0}).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack))", realClsName); } } internal static void GetRefWriteBackValueCode(this Type type, StringBuilder sb, string paramName) { if (type.IsPrimitive) { if (type == typeof(int)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;"); sb.Append(" ___dst->Value = " + paramName); sb.AppendLine(";"); } else if (type == typeof(long)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Long;"); sb.Append(" *(long*)&___dst->Value = " + paramName); sb.AppendLine(";"); } else if (type == typeof(short)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;"); sb.Append(" ___dst->Value = " + paramName); sb.AppendLine(";"); } else if (type == typeof(bool)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;"); sb.Append(" ___dst->Value = " + paramName + " ? 1 : 0;"); sb.AppendLine(";"); } else if (type == typeof(ushort)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;"); sb.Append(" ___dst->Value = " + paramName); sb.AppendLine(";"); } else if (type == typeof(float)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Float;"); sb.Append(" *(float*)&___dst->Value = " + paramName); sb.AppendLine(";"); } else if (type == typeof(double)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Double;"); sb.Append(" *(double*)&___dst->Value = " + paramName); sb.AppendLine(";"); } else if (type == typeof(byte)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;"); sb.Append(" ___dst->Value = " + paramName); sb.AppendLine(";"); } else if (type == typeof(sbyte)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;"); sb.Append(" ___dst->Value = " + paramName); sb.AppendLine(";"); } else if (type == typeof(uint)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;"); sb.Append(" ___dst->Value = (int)" + paramName); sb.AppendLine(";"); } else if (type == typeof(char)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Integer;"); sb.Append(" ___dst->Value = (int)" + paramName); sb.AppendLine(";"); } else if (type == typeof(ulong)) { sb.AppendLine(" ___dst->ObjectType = ObjectTypes.Long;"); sb.Append(" *(ulong*)&___dst->Value = " + paramName); sb.AppendLine(";"); } else throw new NotImplementedException(); } else { if (!type.IsValueType) { sb.Append(@" object ___obj = "); sb.Append(paramName); sb.AppendLine(";"); sb.AppendLine(@" if (___obj is CrossBindingAdaptorType) ___obj = ((CrossBindingAdaptorType)___obj).ILInstance; __mStack[___dst->Value] = ___obj; "); } else { sb.Append(" __mStack[___dst->Value] = "); sb.Append(paramName); sb.AppendLine(";"); } } } internal static void GetReturnValueCode(this Type type, StringBuilder sb) { if (type.IsPrimitive) { if (type == typeof(int)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;"); sb.AppendLine(" __ret->Value = result_of_this_method;"); } else if (type == typeof(long)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Long;"); sb.AppendLine(" *(long*)&__ret->Value = result_of_this_method;"); } else if (type == typeof(short)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;"); sb.AppendLine(" __ret->Value = result_of_this_method;"); } else if (type == typeof(bool)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;"); sb.AppendLine(" __ret->Value = result_of_this_method ? 1 : 0;"); } else if (type == typeof(ushort)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;"); sb.AppendLine(" __ret->Value = result_of_this_method;"); } else if (type == typeof(float)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Float;"); sb.AppendLine(" *(float*)&__ret->Value = result_of_this_method;"); } else if (type == typeof(double)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Double;"); sb.AppendLine(" *(double*)&__ret->Value = result_of_this_method;"); } else if (type == typeof(byte)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;"); sb.AppendLine(" __ret->Value = result_of_this_method;"); } else if (type == typeof(sbyte)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;"); sb.AppendLine(" __ret->Value = result_of_this_method;"); } else if (type == typeof(uint)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;"); sb.AppendLine(" __ret->Value = (int)result_of_this_method;"); } else if (type == typeof(char)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Integer;"); sb.AppendLine(" __ret->Value = (int)result_of_this_method;"); } else if (type == typeof(ulong)) { sb.AppendLine(" __ret->ObjectType = ObjectTypes.Long;"); sb.AppendLine(" *(ulong*)&__ret->Value = result_of_this_method;"); } else throw new NotImplementedException(); sb.AppendLine(" return __ret + 1;"); } else { if (!type.IsSealed && type != typeof(ILRuntime.Runtime.Intepreter.ILTypeInstance)) { sb.AppendLine(@" object obj_result_of_this_method = result_of_this_method; if(obj_result_of_this_method is CrossBindingAdaptorType) { return ILIntepreter.PushObject(__ret, __mStack, ((CrossBindingAdaptorType)obj_result_of_this_method).ILInstance); }"); } sb.AppendLine(" return ILIntepreter.PushObject(__ret, __mStack, result_of_this_method);"); } } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/CLRBinding/CommonBindingGenerator.cs ================================================ using System; using System.Collections.Generic; using System.Reflection; using System.Linq; using System.Text; using ILRuntime.Runtime.Enviorment; namespace ILRuntime.Runtime.CLRBinding { static class CommonBindingGenerator { internal static string GenerateMiscRegisterCode(this Type type, string typeClsName, bool defaultCtor, bool newArr) { StringBuilder sb = new StringBuilder(); if (defaultCtor && !type.IsPrimitive && !type.IsAbstract) { var constructorFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; var hasDefaultConstructor = type.GetConstructor(constructorFlags, null, new Type[0], null) != null; if (hasDefaultConstructor || type.IsValueType) { sb.AppendLine(string.Format(" app.RegisterCLRCreateDefaultInstance(type, () => new {0}());", typeClsName)); } } if (newArr) { if (!type.IsAbstract || !type.IsSealed) { sb.AppendLine(string.Format(" app.RegisterCLRCreateArrayInstance(type, s => new {0}[s]);", typeClsName)); } } return sb.ToString(); } internal static string GenerateCommonCode(this Type type, string typeClsName) { if (!type.IsValueType) return ""; StringBuilder sb = new StringBuilder(); if (type.IsPrimitive) { sb.AppendLine(string.Format(" static {0} GetInstance(ILRuntime.Runtime.Enviorment.AppDomain __domain, StackObject* ptr_of_this_method, IList __mStack)", typeClsName)); sb.AppendLine(" {"); if (type.IsPrimitive || type.IsValueType) sb.AppendLine(" ptr_of_this_method = ILIntepreter.GetObjectAndResolveReference(ptr_of_this_method);"); sb.AppendLine(string.Format(" {0} instance_of_this_method;", typeClsName)); sb.Append(@" switch(ptr_of_this_method->ObjectType) { case ObjectTypes.FieldReference: { var instance_of_fieldReference = __mStack[ptr_of_this_method->Value]; if(instance_of_fieldReference is ILTypeInstance) { instance_of_this_method = ("); sb.Append(typeClsName); sb.Append(")"); if(type == typeof(bool)) { sb.Append("((int)"); } sb.Append("((ILTypeInstance)instance_of_fieldReference)[ptr_of_this_method->ValueLow]"); if (type == typeof(bool)) { sb.Append(" == 1);"); } else sb.Append(";"); sb.Append(@" } else { var t = __domain.GetType(instance_of_fieldReference.GetType()) as CLRType; instance_of_this_method = ("); sb.Append(typeClsName); sb.Append(")t.GetFieldValue(ptr_of_this_method->ValueLow, instance_of_fieldReference);"); sb.Append(@" } } break; case ObjectTypes.StaticFieldReference: { var t = __domain.GetType(ptr_of_this_method->Value); if(t is ILType) { instance_of_this_method = ("); sb.Append(typeClsName); sb.Append(")"); if (type == typeof(bool)) { sb.Append("((int)"); } sb.Append("((ILType)t).StaticInstance[ptr_of_this_method->ValueLow]"); if (type == typeof(bool)) { sb.Append(" == 1);"); } else sb.Append(";"); sb.Append(@" } else { instance_of_this_method = ("); sb.Append(typeClsName); sb.Append(@")((CLRType)t).GetFieldValue(ptr_of_this_method->ValueLow, null); } } break; case ObjectTypes.ArrayReference: { var instance_of_arrayReference = __mStack[ptr_of_this_method->Value] as "); sb.Append(typeClsName); sb.AppendLine(@"[]; instance_of_this_method = instance_of_arrayReference[ptr_of_this_method->ValueLow]; } break; default:"); sb.AppendLine(string.Format(" instance_of_this_method = {0};", type.GetRetrieveValueCode(typeClsName))); sb.AppendLine(@" break; } return instance_of_this_method;"); sb.AppendLine(" }"); } if (!type.IsPrimitive && !type.IsAbstract) { sb.AppendLine(string.Format(" static void WriteBackInstance(ILRuntime.Runtime.Enviorment.AppDomain __domain, StackObject* ptr_of_this_method, IList __mStack, ref {0} instance_of_this_method)", typeClsName)); sb.AppendLine(" {"); sb.AppendLine(@" ptr_of_this_method = ILIntepreter.GetObjectAndResolveReference(ptr_of_this_method); switch(ptr_of_this_method->ObjectType) { case ObjectTypes.Object: { __mStack[ptr_of_this_method->Value] = instance_of_this_method;"); sb.Append(@" } break; case ObjectTypes.FieldReference: { var ___obj = __mStack[ptr_of_this_method->Value]; if(___obj is ILTypeInstance) { ((ILTypeInstance)___obj)[ptr_of_this_method->ValueLow] = instance_of_this_method"); sb.Append(@"; } else { var t = __domain.GetType(___obj.GetType()) as CLRType; t.SetFieldValue(ptr_of_this_method->ValueLow, ref ___obj, instance_of_this_method"); sb.Append(@"); } } break; case ObjectTypes.StaticFieldReference: { var t = __domain.GetType(ptr_of_this_method->Value); if(t is ILType) { ((ILType)t).StaticInstance[ptr_of_this_method->ValueLow] = instance_of_this_method"); sb.Append(@"; } else { ((CLRType)t).SetStaticFieldValue(ptr_of_this_method->ValueLow, instance_of_this_method"); sb.Append(@"); } } break; case ObjectTypes.ArrayReference: { var instance_of_arrayReference = __mStack[ptr_of_this_method->Value] as "); sb.Append(typeClsName); sb.AppendLine(@"[]; instance_of_arrayReference[ptr_of_this_method->ValueLow] = instance_of_this_method; } break; }"); sb.AppendLine(@" }"); } return sb.ToString(); } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/CLRBinding/ConstructorBindingGenerator.cs ================================================ using System; using System.Collections.Generic; using System.Reflection; using System.Linq; using System.Text; using ILRuntime.Runtime.Enviorment; namespace ILRuntime.Runtime.CLRBinding { static class ConstructorBindingGenerator { internal static string GenerateConstructorRegisterCode(this Type type, ConstructorInfo[] methods, HashSet excludes) { StringBuilder sb = new StringBuilder(); int idx = 0; foreach (var i in methods) { if (excludes != null && excludes.Contains(i)) continue; if (type.ShouldSkipMethod(i)) continue; var param = i.GetParameters(); StringBuilder sb2 = new StringBuilder(); sb2.Append("{"); bool first = true; foreach (var j in param) { if (first) first = false; else sb2.Append(", "); sb2.Append("typeof("); string tmp, clsName; bool isByRef; j.ParameterType.GetClassName(out tmp, out clsName, out isByRef); sb2.Append(clsName); sb2.Append(")"); if (isByRef) sb2.Append(".MakeByRefType()"); } sb2.Append("}"); sb.AppendLine(string.Format(" args = new Type[]{0};", sb2)); sb.AppendLine(" method = type.GetConstructor(flag, null, args, null);"); sb.AppendLine(string.Format(" app.RegisterCLRMethodRedirection(method, Ctor_{0});",idx)); idx++; } return sb.ToString(); } internal static string GenerateConstructorWraperCode(this Type type, ConstructorInfo[] methods, string typeClsName, HashSet excludes) { StringBuilder sb = new StringBuilder(); int idx = 0; foreach (var i in methods) { if (excludes != null && excludes.Contains(i)) continue; if (type.ShouldSkipMethod(i) || i.IsStatic) continue; var param = i.GetParameters(); int paramCnt = param.Length; sb.AppendLine(string.Format(" static StackObject* Ctor_{0}(ILIntepreter __intp, StackObject* __esp, IList __mStack, CLRMethod __method, bool isNewObj)", idx)); sb.AppendLine(" {"); sb.AppendLine(" ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain;"); sb.AppendLine(" StackObject* ptr_of_this_method;"); sb.AppendLine(string.Format(" StackObject* __ret = ILIntepreter.Minus(__esp, {0});", paramCnt)); for (int j = param.Length; j > 0; j--) { var p = param[j - 1]; sb.AppendLine(string.Format(" ptr_of_this_method = ILIntepreter.Minus(__esp, {0});", param.Length - j + 1)); string tmp, clsName; bool isByRef; p.ParameterType.GetClassName(out tmp, out clsName, out isByRef); if (isByRef) sb.AppendLine(" ptr_of_this_method = ILIntepreter.GetObjectAndResolveReference(ptr_of_this_method);"); sb.AppendLine(string.Format(" {0} {1} = {2};", clsName, p.Name, p.ParameterType.GetRetrieveValueCode(clsName))); if (!isByRef && !p.ParameterType.IsPrimitive) sb.AppendLine(" __intp.Free(ptr_of_this_method);"); } sb.AppendLine(); sb.Append(" var result_of_this_method = "); { string tmp, clsName; bool isByRef; type.GetClassName(out tmp, out clsName, out isByRef); sb.Append(string.Format("new {0}(", clsName)); param.AppendParameters(sb); sb.AppendLine(");"); } sb.AppendLine(); if (type.IsValueType) { sb.AppendLine(@" if(!isNewObj) { __ret--; WriteBackInstance(__domain, __ret, __mStack, ref result_of_this_method); return __ret; }"); } //Ref/Out for (int j = param.Length; j > 0; j--) { var p = param[j - 1]; if (!p.ParameterType.IsByRef) continue; string tmp, clsName; bool isByRef; p.ParameterType.GetElementType().GetClassName(out tmp, out clsName, out isByRef); sb.AppendLine(string.Format(" ptr_of_this_method = ILIntepreter.Minus(__esp, {0});", param.Length - j + 1)); sb.AppendLine(@" switch(ptr_of_this_method->ObjectType) { case ObjectTypes.StackObjectReference: { var ___dst = *(StackObject**)&ptr_of_this_method->Value;"); p.ParameterType.GetElementType().GetRefWriteBackValueCode(sb, p.Name); sb.Append(@" } break; case ObjectTypes.FieldReference: { var ___obj = __mStack[ptr_of_this_method->Value]; if(___obj is ILTypeInstance) { ((ILTypeInstance)___obj)[ptr_of_this_method->ValueLow] = "); sb.Append(p.Name); sb.Append(@"; } else { var t = __domain.GetType(___obj.GetType()) as CLRType; t.SetFieldValue(ptr_of_this_method->ValueLow, ref ___obj, "); sb.Append(p.Name); sb.Append(@"); } } break; case ObjectTypes.StaticFieldReference: { var t = __domain.GetType(ptr_of_this_method->Value); if(t is ILType) { ((ILType)t).StaticInstance[ptr_of_this_method->ValueLow] = "); sb.Append(p.Name); sb.Append(@"; } else { ((CLRType)t).SetStaticFieldValue(ptr_of_this_method->ValueLow, "); sb.Append(p.Name); sb.Append(@"); } } break; case ObjectTypes.ArrayReference: { var instance_of_arrayReference = __mStack[ptr_of_this_method->Value] as "); sb.Append(clsName); sb.Append(@"[]; instance_of_arrayReference[ptr_of_this_method->ValueLow] = "); sb.Append(p.Name); sb.AppendLine(@"; } break; }"); sb.AppendLine(); } sb.AppendLine(" return ILIntepreter.PushObject(__ret, __mStack, result_of_this_method);"); sb.AppendLine(" }"); sb.AppendLine(); idx++; } return sb.ToString(); } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/CLRBinding/FieldBindingGenerator.cs ================================================ using System; using System.Collections.Generic; using System.Reflection; using System.Linq; using System.Text; using ILRuntime.Runtime.Enviorment; namespace ILRuntime.Runtime.CLRBinding { static class FieldBindingGenerator { internal static string GenerateFieldRegisterCode(this Type type, FieldInfo[] fields, HashSet excludes) { StringBuilder sb = new StringBuilder(); int idx = 0; foreach (var i in fields) { if (excludes != null && excludes.Contains(i)) continue; if (type.ShouldSkipField(i)) continue; if (i.IsSpecialName) continue; sb.AppendLine(string.Format(" field = type.GetField(\"{0}\", flag);", i.Name)); sb.AppendLine(string.Format(" app.RegisterCLRFieldGetter(field, get_{0}_{1});", i.Name, idx)); if (!i.IsInitOnly && !i.IsLiteral) { sb.AppendLine(string.Format(" app.RegisterCLRFieldSetter(field, set_{0}_{1});", i.Name, idx)); } idx++; } return sb.ToString(); } internal static string GenerateFieldWraperCode(this Type type, FieldInfo[] fields, string typeClsName, HashSet excludes) { StringBuilder sb = new StringBuilder(); int idx = 0; foreach (var i in fields) { if (excludes != null && excludes.Contains(i)) continue; if (type.ShouldSkipField(i)) continue; sb.AppendLine(string.Format(" static object get_{0}_{1}(ref object o)", i.Name, idx)); sb.AppendLine(" {"); if (i.IsStatic) { sb.AppendLine(string.Format(" return {0}.{1};", typeClsName, i.Name)); } else { sb.AppendLine(string.Format(" return (({0})o).{1};", typeClsName, i.Name)); } sb.AppendLine(" }"); if (!i.IsInitOnly && !i.IsLiteral) { sb.AppendLine(string.Format(" static void set_{0}_{1}(ref object o, object v)", i.Name, idx)); sb.AppendLine(" {"); string clsName, realClsName; bool isByRef; i.FieldType.GetClassName(out clsName, out realClsName, out isByRef); if (i.IsStatic) { sb.AppendLine(string.Format(" {0}.{1} = ({2})v;", typeClsName, i.Name, realClsName)); } else { if (CheckCanPinn(type)) { sb.AppendLine(" var h = GCHandle.Alloc(o, GCHandleType.Pinned);"); sb.AppendLine(string.Format(" {0}* p = ({0} *)(void *)h.AddrOfPinnedObject();", typeClsName)); sb.AppendLine(string.Format(" p->{0} = ({1})v;", i.Name, realClsName)); sb.AppendLine(" h.Free();"); } else { sb.AppendLine(string.Format(" (({0})o).{1} = ({2})v;", typeClsName, i.Name, realClsName)); } } sb.AppendLine(" }"); } idx++; } return sb.ToString(); } internal static bool CheckCanPinn(this Type type) { if (type.IsValueType) { FieldInfo[] fi = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); bool res = true; foreach(var i in fi) { if(!i.FieldType.IsPrimitive) { res = false; break; } } return res; } else return false; } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/CLRBinding/MethodBindingGenerator.cs ================================================ using System; using System.Collections.Generic; using System.Reflection; using System.Linq; using System.Text; using ILRuntime.Runtime.Enviorment; namespace ILRuntime.Runtime.CLRBinding { static class MethodBindingGenerator { internal static string GenerateMethodRegisterCode(this Type type, MethodInfo[] methods, HashSet excludes) { StringBuilder sb = new StringBuilder(); int idx = 0; foreach (var i in methods) { if (excludes != null && excludes.Contains(i)) continue; if (type.ShouldSkipMethod(i)) continue; bool isProperty = i.IsSpecialName; var param = i.GetParameters(); StringBuilder sb2 = new StringBuilder(); sb2.Append("{"); bool first = true; foreach (var j in param) { if (first) first = false; else sb2.Append(", "); sb2.Append("typeof("); string tmp, clsName; bool isByRef; j.ParameterType.GetClassName(out tmp, out clsName, out isByRef); sb2.Append(clsName); sb2.Append(")"); if (isByRef) sb2.Append(".MakeByRefType()"); } sb2.Append("}"); sb.AppendLine(string.Format(" args = new Type[]{0};", sb2)); sb.AppendLine(string.Format(" method = type.GetMethod(\"{0}\", flag, null, args, null);", i.Name)); sb.AppendLine(string.Format(" app.RegisterCLRMethodRedirection(method, {0}_{1});", i.Name, idx)); idx++; } return sb.ToString(); } internal static string GenerateMethodWraperCode(this Type type, MethodInfo[] methods, string typeClsName, HashSet excludes) { StringBuilder sb = new StringBuilder(); int idx = 0; foreach (var i in methods) { if (excludes != null && excludes.Contains(i)) continue; if (type.ShouldSkipMethod(i)) continue; bool isProperty = i.IsSpecialName; var param = i.GetParameters(); int paramCnt = param.Length; if (!i.IsStatic) paramCnt++; sb.AppendLine(string.Format(" static StackObject* {0}_{1}(ILIntepreter __intp, StackObject* __esp, IList __mStack, CLRMethod __method, bool isNewObj)", i.Name, idx)); sb.AppendLine(" {"); sb.AppendLine(" ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain;"); sb.AppendLine(" StackObject* ptr_of_this_method;"); sb.AppendLine(string.Format(" StackObject* __ret = ILIntepreter.Minus(__esp, {0});", paramCnt)); for (int j = param.Length; j > 0; j--) { var p = param[j - 1]; sb.AppendLine(string.Format(" ptr_of_this_method = ILIntepreter.Minus(__esp, {0});", param.Length - j + 1)); string tmp, clsName; bool isByRef; p.ParameterType.GetClassName(out tmp, out clsName, out isByRef); if (isByRef) sb.AppendLine(" ptr_of_this_method = ILIntepreter.GetObjectAndResolveReference(ptr_of_this_method);"); sb.AppendLine(string.Format(" {0} {1} = {2};", clsName, p.Name, p.ParameterType.GetRetrieveValueCode(clsName))); if (!isByRef && !p.ParameterType.IsPrimitive) sb.AppendLine(" __intp.Free(ptr_of_this_method);"); } if (!i.IsStatic) { sb.AppendLine(string.Format(" ptr_of_this_method = ILIntepreter.Minus(__esp, {0});", paramCnt)); if (type.IsPrimitive) sb.AppendLine(string.Format(" {0} instance_of_this_method = GetInstance(__domain, ptr_of_this_method, __mStack);", typeClsName)); else { if (type.IsValueType) sb.AppendLine(" ptr_of_this_method = ILIntepreter.GetObjectAndResolveReference(ptr_of_this_method);"); sb.AppendLine(string.Format(" {0} instance_of_this_method;", typeClsName)); sb.AppendLine(string.Format(" instance_of_this_method = {0};", type.GetRetrieveValueCode(typeClsName))); if (!type.IsValueType) sb.AppendLine(" __intp.Free(ptr_of_this_method);"); } } sb.AppendLine(); if (i.ReturnType != typeof(void)) { sb.Append(" var result_of_this_method = "); } else sb.Append(" "); if (i.IsStatic) { if (isProperty) { string[] t = i.Name.Split('_'); string propType = t[0]; if (propType == "get") { bool isIndexer = param.Length > 0; if (isIndexer) { sb.AppendLine(string.Format("{1}[{0}];", param[0].Name, typeClsName)); } else sb.AppendLine(string.Format("{1}.{0};", t[1], typeClsName)); } else if (propType == "set") { bool isIndexer = param.Length > 1; if (isIndexer) { sb.AppendLine(string.Format("{2}[{0}] = {1};", param[0].Name, param[1].Name, typeClsName)); } else sb.AppendLine(string.Format("{2}.{0} = {1};", t[1], param[0].Name, typeClsName)); } else if (propType == "op") { switch (t[1]) { case "Equality": sb.AppendLine(string.Format("{0} == {1};", param[0].Name, param[1].Name)); break; case "Inequality": sb.AppendLine(string.Format("{0} != {1};", param[0].Name, param[1].Name)); break; case "Addition": sb.AppendLine(string.Format("{0} + {1};", param[0].Name, param[1].Name)); break; case "Subtraction": sb.AppendLine(string.Format("{0} - {1};", param[0].Name, param[1].Name)); break; case "Multiply": sb.AppendLine(string.Format("{0} * {1};", param[0].Name, param[1].Name)); break; case "Division": sb.AppendLine(string.Format("{0} / {1};", param[0].Name, param[1].Name)); break; case "GreaterThan": sb.AppendLine(string.Format("{0} > {1};", param[0].Name, param[1].Name)); break; case "GreaterThanOrEqual": sb.AppendLine(string.Format("{0} >= {1};", param[0].Name, param[1].Name)); break; case "LessThan": sb.AppendLine(string.Format("{0} < {1};", param[0].Name, param[1].Name)); break; case "LessThanOrEqual": sb.AppendLine(string.Format("{0} <= {1};", param[0].Name, param[1].Name)); break; case "UnaryNegation": sb.AppendLine(string.Format("-{0};", param[0].Name)); break; case "Implicit": case "Explicit": { string tmp, clsName; bool isByRef; i.ReturnType.GetClassName(out tmp, out clsName, out isByRef); sb.AppendLine(string.Format("({1}){0};", param[0].Name, clsName)); } break; default: throw new NotImplementedException(i.Name); } } else throw new NotImplementedException(); } else { sb.Append(string.Format("{0}.{1}(", typeClsName, i.Name)); param.AppendParameters(sb); sb.AppendLine(");"); } } else { if (isProperty) { string[] t = i.Name.Split('_'); string propType = t[0]; if (propType == "get") { bool isIndexer = param.Length > 0; if (isIndexer) { sb.AppendLine(string.Format("instance_of_this_method[{0}];", param[0].Name)); } else sb.AppendLine(string.Format("instance_of_this_method.{0};", t[1])); } else if (propType == "set") { bool isIndexer = param.Length > 1; if (isIndexer) { sb.AppendLine(string.Format("instance_of_this_method[{0}] = {1};", param[0].Name, param[1].Name)); } else sb.AppendLine(string.Format("instance_of_this_method.{0} = {1};", t[1], param[0].Name)); } else throw new NotImplementedException(); } else { sb.Append(string.Format("instance_of_this_method.{0}(", i.Name)); param.AppendParameters(sb); sb.AppendLine(");"); } } sb.AppendLine(); if (!i.IsStatic && type.IsValueType && !type.IsPrimitive)//need to write back value type instance { sb.AppendLine(" WriteBackInstance(__domain, ptr_of_this_method, __mStack, ref instance_of_this_method);"); sb.AppendLine(); } //Ref/Out for (int j = param.Length; j > 0; j--) { var p = param[j - 1]; if (!p.ParameterType.IsByRef) continue; string tmp, clsName; bool isByRef; p.ParameterType.GetElementType().GetClassName(out tmp, out clsName, out isByRef); sb.AppendLine(string.Format(" ptr_of_this_method = ILIntepreter.Minus(__esp, {0});", param.Length - j + 1)); sb.AppendLine(@" switch(ptr_of_this_method->ObjectType) { case ObjectTypes.StackObjectReference: { var ___dst = *(StackObject**)&ptr_of_this_method->Value;"); p.ParameterType.GetElementType().GetRefWriteBackValueCode(sb, p.Name); sb.Append(@" } break; case ObjectTypes.FieldReference: { var ___obj = __mStack[ptr_of_this_method->Value]; if(___obj is ILTypeInstance) { ((ILTypeInstance)___obj)[ptr_of_this_method->ValueLow] = "); sb.Append(p.Name); sb.Append(@"; } else { var t = __domain.GetType(___obj.GetType()) as CLRType; t.SetFieldValue(ptr_of_this_method->ValueLow, ref ___obj, "); sb.Append(p.Name); sb.Append(@"); } } break; case ObjectTypes.StaticFieldReference: { var t = __domain.GetType(ptr_of_this_method->Value); if(t is ILType) { ((ILType)t).StaticInstance[ptr_of_this_method->ValueLow] = "); sb.Append(p.Name); sb.Append(@"; } else { ((CLRType)t).SetStaticFieldValue(ptr_of_this_method->ValueLow, "); sb.Append(p.Name); sb.Append(@"); } } break; case ObjectTypes.ArrayReference: { var instance_of_arrayReference = __mStack[ptr_of_this_method->Value] as "); sb.Append(clsName); sb.Append(@"[]; instance_of_arrayReference[ptr_of_this_method->ValueLow] = "); sb.Append(p.Name); sb.AppendLine(@"; } break; }"); sb.AppendLine(); } if (i.ReturnType != typeof(void)) { i.ReturnType.GetReturnValueCode(sb); } else sb.AppendLine(" return __ret;"); sb.AppendLine(" }"); sb.AppendLine(); idx++; } return sb.ToString(); } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/CLRBinding/ValueTypeBindingGenerator.cs ================================================ using System; using System.Collections.Generic; using System.Reflection; using System.Linq; using System.Text; using ILRuntime.Runtime.Enviorment; namespace ILRuntime.Runtime.CLRBinding { static class ValueTypeBindingGenerator { internal static string GenerateValueTypeRegisterCode(this Type type, string typeClsName) { StringBuilder sb = new StringBuilder(); if (type.IsValueType && !type.IsPrimitive && !type.IsEnum) { sb.AppendLine(" app.RegisterCLRMemberwiseClone(type, PerformMemberwiseClone);"); } return sb.ToString(); } internal static string GenerateCloneWraperCode(this Type type, FieldInfo[] fields, string typeClsName) { if (!type.IsValueType || type.IsPrimitive) return string.Empty; StringBuilder sb = new StringBuilder(); sb.AppendLine(" static object PerformMemberwiseClone(ref object o)"); sb.AppendLine(" {"); sb.AppendLine(string.Format(" return new {0}", typeClsName)); sb.AppendLine(" {"); foreach (var i in fields) { if (i.IsStatic || i.IsInitOnly || i.IsLiteral) continue; sb.AppendLine(string.Format(" {0} = (({1}) o).{0},", i.Name, typeClsName)); } sb.AppendLine(" };"); sb.AppendLine(" }"); return sb.ToString(); } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/BreakPointContext.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Stack; namespace ILRuntime.Runtime.Debugger { unsafe class BreakPointContext { public ILIntepreter Interpreter { get; set; } public Exception Exception { get; set; } public string DumpContext() { /*StringBuilder sb = new StringBuilder(); if (Exception != null) sb.AppendLine(Exception.Message); StackFrame[] frames = Interpreter.Stack.Frames.ToArray(); StackFrame topFrame = frames[0]; var m = topFrame.Method; if (m.HasThis) { sb.AppendLine("this:"); sb.AppendLine(DebugService.Instance.GetThisInfo(Interpreter)); } sb.AppendLine("->" + topFrame.Method.Definition.Body.Instructions[topFrame.Address.Value]); sb.AppendLine("Local Variables:"); sb.AppendLine(DebugService.Instance.GetLocalVariableInfo(Interpreter)); sb.Append(DebugService.Instance.GetStackTrance(Interpreter)); return sb.ToString();*/ return null; } string GetStackObjectValue(StackObject val, IList mStack) { string v; switch (val.ObjectType) { case ObjectTypes.Null: v = "null"; break; case ObjectTypes.Integer: v = val.Value.ToString(); break; case ObjectTypes.Object: { object obj = Interpreter.Stack.ManagedStack[val.Value]; v = obj.ToString(); } break; default: v = "Unknown type"; break; } return v; } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/BreakpointInfo.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger { class BreakpointInfo { public int BreakpointHashCode { get; set; } public int MethodHashCode { get; set; } public int StartLine { get; set; } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/DebugMessageType.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger { public enum DebugMessageType { CSAttach, SCAttachResult, CSBindBreakpoint, SCBindBreakpointResult, SCModuleLoaded, SCThreadStarted, SCThreadEnded, SCBreakpointHit, CSDeleteBreakpoint, CSExecute, CSStep, SCStepComplete, CSResolveVariable, SCResolveVariableResult } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/DebugService.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Stack; using ILRuntime.CLR.Utils; namespace ILRuntime.Runtime.Debugger { public class DebugService { BreakPointContext curBreakpoint; DebuggerServer server; Runtime.Enviorment.AppDomain domain; Dictionary> activeBreakpoints = new Dictionary>(); Dictionary breakpointMapping = new Dictionary(); AutoResetEvent evt = new AutoResetEvent(false); public Action OnBreakPoint; public Enviorment.AppDomain AppDomain { get { return domain; } } public AutoResetEvent BlockEvent { get { return evt; } } public bool IsDebuggerAttached { get { #if DEBUG return (server != null && server.IsAttached); #else return false; #endif } } public DebugService(Runtime.Enviorment.AppDomain domain) { this.domain = domain; } /// /// Start Debugger Server /// /// Port to listen on public void StartDebugService(int port) { #if DEBUG server = new Debugger.DebuggerServer(this); server.Port = port; server.Start(); #endif } /// /// Stop Debugger Server /// public void StopDebugService() { #if DEBUG server.Stop(); server = null; #endif } /// /// 中断运行 /// /// /// /// 如果挂的有调试器则返回true internal bool Break(ILIntepreter intpreter, Exception ex = null) { BreakPointContext ctx = new BreakPointContext(); ctx.Interpreter = intpreter; ctx.Exception = ex; curBreakpoint = ctx; if (OnBreakPoint != null) { OnBreakPoint(ctx.DumpContext()); return true; } return false; } public string GetStackTrance(ILIntepreter intepreper) { StringBuilder sb = new StringBuilder(); ILRuntime.CLR.Method.ILMethod m; StackFrame[] frames = intepreper.Stack.Frames.ToArray(); Mono.Cecil.Cil.Instruction ins = null; if (frames[0].Address != null) { ins = frames[0].Method.Definition.Body.Instructions[frames[0].Address.Value]; sb.AppendLine(ins.ToString()); } for (int i = 0; i < frames.Length; i++) { var f = frames[i]; m = f.Method; string document = ""; if (f.Address != null) { ins = m.Definition.Body.Instructions[f.Address.Value]; var seq = FindSequencePoint(ins); if (seq != null) { document = string.Format("{0}:Line {1}", seq.Document.Url, seq.StartLine); } } sb.AppendFormat("at {0} {1}\r\n", m, document); } return sb.ToString(); } public unsafe string GetThisInfo(ILIntepreter intepreter) { var topFrame = intepreter.Stack.Frames.Peek(); var arg = Minus(topFrame.LocalVarPointer, topFrame.Method.ParameterCount); if (topFrame.Method.HasThis) arg--; if (arg->ObjectType == ObjectTypes.StackObjectReference) { arg = *(StackObject**)&arg->Value; } ILTypeInstance instance = arg->ObjectType != ObjectTypes.Null ? intepreter.Stack.ManagedStack[arg->Value] as ILTypeInstance : null; if (instance == null) return "null"; var fields = instance.Type.TypeDefinition.Fields; int idx = 0; StringBuilder sb = new StringBuilder(); for (int i = 0; i < fields.Count; i++) { var f = fields[i]; if (f.IsStatic) continue; var field = instance.Fields[idx]; var v = StackObject.ToObject(&field, intepreter.AppDomain, instance.ManagedObjects); if (v == null) v = "null"; string name = f.Name; sb.AppendFormat("{0} {1} = {2}", f.FieldType.Name, name, v); if ((idx % 3 == 0 && idx != 0) || idx == instance.Fields.Length - 1) sb.AppendLine(); else sb.Append(", "); idx++; } return sb.ToString(); } public unsafe string GetLocalVariableInfo(ILIntepreter intepreter) { StackFrame topFrame = intepreter.Stack.Frames.Peek(); var m = topFrame.Method; StringBuilder sb = new StringBuilder(); for (int i = 0; i < m.LocalVariableCount; i++) { var lv = m.Definition.Body.Variables[i]; var val = Add(topFrame.LocalVarPointer, i); var v = StackObject.ToObject(val, intepreter.AppDomain, intepreter.Stack.ManagedStack); if (v == null) v = "null"; string name = string.IsNullOrEmpty(lv.Name) ? "v" + lv.Index : lv.Name; sb.AppendFormat("{0} {1} = {2}", lv.VariableType.Name, name, v); if ((i % 3 == 0 && i != 0) || i == m.LocalVariableCount - 1) sb.AppendLine(); else sb.Append(", "); } return sb.ToString(); } internal static Mono.Cecil.Cil.SequencePoint FindSequencePoint(Mono.Cecil.Cil.Instruction ins) { Mono.Cecil.Cil.Instruction cur = ins; while (cur.SequencePoint == null && cur.Previous != null) cur = cur.Previous; return cur.SequencePoint; } unsafe StackObject* Add(StackObject* a, int b) { return (StackObject*)((long)a + sizeof(StackObject) * b); } unsafe StackObject* Minus(StackObject* a, int b) { return (StackObject*)((long)a - sizeof(StackObject) * b); } internal void NotifyModuleLoaded(string moduleName) { if (server != null && server.IsAttached) server.NotifyModuleLoaded(moduleName); } internal void SetBreakPoint(int methodHash, int bpHash, int startLine) { lock (activeBreakpoints) { LinkedList lst; if(!activeBreakpoints.TryGetValue(methodHash, out lst)) { lst = new LinkedList(); activeBreakpoints[methodHash] = lst; } BreakpointInfo bpInfo = new BreakpointInfo(); bpInfo.BreakpointHashCode = bpHash; bpInfo.MethodHashCode = methodHash; bpInfo.StartLine = startLine; lst.AddLast(bpInfo); breakpointMapping[bpHash] = bpInfo; } } internal void DeleteBreakpoint(int bpHash) { lock (activeBreakpoints) { BreakpointInfo bpInfo; if (breakpointMapping.TryGetValue(bpHash, out bpInfo)) { LinkedList lst; if(activeBreakpoints.TryGetValue(bpInfo.MethodHashCode, out lst)) { lst.Remove(bpInfo); } breakpointMapping.Remove(bpHash); } } } internal void ExecuteThread(int threadHash) { lock (AppDomain.FreeIntepreters) { foreach(var i in AppDomain.Intepreters) { //We should resume all threads on execute i.Value.ClearDebugState(); i.Value.Resume(); } } } internal unsafe void StepThread(int threadHash, StepTypes type) { lock (AppDomain.FreeIntepreters) { ILIntepreter intp; if(AppDomain.Intepreters.TryGetValue(threadHash, out intp)) { intp.ClearDebugState(); intp.CurrentStepType = type; intp.LastStepFrameBase = intp.Stack.Frames.Count > 0 ? intp.Stack.Frames.Peek().BasePointer : (StackObject*)0; intp.LastStepInstructionIndex = intp.Stack.Frames.Count > 0 ? intp.Stack.Frames.Peek().Address.Value : 0; intp.Resume(); } } } unsafe internal void CheckShouldBreak(ILMethod method, ILIntepreter intp, int ip) { if (server != null && server.IsAttached) { int methodHash = method.GetHashCode(); lock (activeBreakpoints) { LinkedList lst; bool bpHit = false; if (activeBreakpoints.TryGetValue(methodHash, out lst)) { var sp = method.Definition.Body.Instructions[ip].SequencePoint; if (sp != null) { foreach (var i in lst) { if ((i.StartLine + 1) == sp.StartLine) { DoBreak(intp, i.BreakpointHashCode, false); bpHit = true; break; } } } } if (!bpHit) { var sp = method.Definition.Body.Instructions[ip].SequencePoint; if (sp != null && IsSequenceValid(sp)) { switch (intp.CurrentStepType) { case StepTypes.Into: DoBreak(intp, 0, true); break; case StepTypes.Over: if (intp.Stack.Frames.Peek().BasePointer <= intp.LastStepFrameBase && ip != intp.LastStepInstructionIndex) { DoBreak(intp, 0, true); } break; case StepTypes.Out: { if (intp.Stack.Frames.Count > 0 && intp.Stack.Frames.Peek().BasePointer < intp.LastStepFrameBase) { DoBreak(intp, 0, true); } } break; } } } } } } bool IsSequenceValid(Mono.Cecil.Cil.SequencePoint sp) { return sp.StartLine != sp.EndLine || sp.StartColumn != sp.EndColumn; } void DoBreak(ILIntepreter intp, int bpHash, bool isStep) { KeyValuePair[] frames = new KeyValuePair[AppDomain.Intepreters.Count]; frames[0] = new KeyValuePair(intp.GetHashCode(), GetStackFrameInfo(intp)); int idx = 1; foreach (var j in AppDomain.Intepreters) { if (j.Value != intp) { j.Value.ShouldBreak = true; frames[idx++] = new KeyValuePair(j.Value.GetHashCode(), GetStackFrameInfo(j.Value)); } } if (!isStep) server.SendSCBreakpointHit(intp.GetHashCode(), bpHash, frames); else server.SendSCStepComplete(intp.GetHashCode(), frames); //Breakpoint hit intp.Break(); } unsafe StackFrameInfo[] GetStackFrameInfo(ILIntepreter intp) { StackFrame[] frames = intp.Stack.Frames.ToArray(); Mono.Cecil.Cil.Instruction ins = null; ILMethod m; StackFrameInfo[] frameInfos = new StackFrameInfo[frames.Length]; for (int j = 0; j < frames.Length; j++) { StackFrameInfo info = new Debugger.StackFrameInfo(); var f = frames[j]; m = f.Method; info.MethodName = m.ToString(); if (f.Address != null) { ins = m.Definition.Body.Instructions[f.Address.Value]; var seq = FindSequencePoint(ins); if (seq != null) { info.DocumentName = seq.Document.Url; info.StartLine = seq.StartLine - 1; info.StartColumn = seq.StartColumn - 1; info.EndLine = seq.EndLine - 1; info.EndColumn = seq.EndColumn - 1; } } StackFrame topFrame = f; m = topFrame.Method; int argumentCount = m.ParameterCount; if (m.HasThis) argumentCount++; info.LocalVariables = new VariableInfo[argumentCount + m.LocalVariableCount]; for(int i = 0; i < argumentCount; i++) { int argIdx = m.HasThis ? i - 1 : i; var arg = Minus(topFrame.LocalVarPointer, argumentCount); string name = null; object v = null; string typeName = null; var val = Add(arg, i); v = StackObject.ToObject(val, intp.AppDomain, intp.Stack.ManagedStack); if (v == null) v = "null"; if (argIdx >= 0) { var lv = m.Definition.Parameters[argIdx]; name = string.IsNullOrEmpty(lv.Name) ? "arg" + lv.Index : lv.Name; typeName = lv.ParameterType.FullName; if (v != null) v = m.Parameters[argIdx].TypeForCLR.CheckCLRTypes(v); } else { name = "this"; typeName = m.DeclearingType.FullName; } VariableInfo vinfo = new Debugger.VariableInfo(); vinfo.Address = (long)val; vinfo.Name = name; vinfo.Value = v.ToString(); vinfo.TypeName = typeName; vinfo.Expandable = GetValueExpandable(val, intp.Stack.ManagedStack); info.LocalVariables[i] = vinfo; } for (int i = argumentCount; i < info.LocalVariables.Length; i++) { var locIdx = i - argumentCount; var lv = m.Definition.Body.Variables[locIdx]; var val = Add(topFrame.LocalVarPointer, locIdx); var v = StackObject.ToObject(val, intp.AppDomain, intp.Stack.ManagedStack); if (v == null) v = "null"; else v = intp.AppDomain.GetType(lv.VariableType, m.DeclearingType, m).TypeForCLR.CheckCLRTypes(v); string name = string.IsNullOrEmpty(lv.Name) ? "v" + lv.Index : lv.Name; VariableInfo vinfo = new Debugger.VariableInfo(); vinfo.Address = (long)val; vinfo.Name = name; vinfo.Value = v.ToString(); vinfo.TypeName = lv.VariableType.FullName; vinfo.Expandable = GetValueExpandable(val, intp.Stack.ManagedStack); info.LocalVariables[i] = vinfo; } frameInfos[j] = info; } return frameInfos; } internal VariableInfo ResolveVariable(VariableReference parent, string name) { return null; } unsafe bool GetValueExpandable(StackObject* esp, IList mStack) { if (esp->ObjectType < ObjectTypes.Object) return false; else { var obj = mStack[esp->Value]; if (obj == null) return false; if (obj is ILTypeInstance) return true; else if (obj.GetType().IsPrimitive) return false; else return true; } } internal void ThreadStarted(ILIntepreter intp) { if (server != null && server.IsAttached) { server.SendSCThreadStarted(intp.GetHashCode()); } } internal void ThreadEnded(ILIntepreter intp) { if (server != null && server.IsAttached) { server.SendSCThreadEnded(intp.GetHashCode()); } } internal void Detach() { activeBreakpoints.Clear(); breakpointMapping.Clear(); foreach (var j in AppDomain.Intepreters) { j.Value.ClearDebugState(); j.Value.Resume(); } } internal unsafe void DumpStack(StackObject* esp, RuntimeStack stack) { #if !UNITY_5 && !UNITY_2017 && !UNITY_4 var start = stack.StackBase; var end = esp + 10; var frames = stack.Frames; var mStack = stack.ManagedStack; var valuePointerEnd = stack.ValueTypeStackPointer; HashSet leakVObj = new HashSet(); for (var i = stack.ValueTypeStackBase; i > stack.ValueTypeStackPointer;) { leakVObj.Add((long)i); i = Minus(i, i->ValueLow + 1); } for (var i = start; i <= end; i++) { StringBuilder sb = new StringBuilder(); ILMethod localMethod = null, baseMethod = null; bool isLocal = false; bool isBase = false; int localIdx = 0; if (i == esp) sb.Append("->"); foreach (var j in frames) { if (i >= j.LocalVarPointer && i < j.BasePointer) { isLocal = true; localIdx = (int)(i - j.LocalVarPointer); localMethod = j.Method; } else if (i == j.BasePointer) { isBase = true; baseMethod = j.Method; } } sb.Append(string.Format("(0x{0:X8}) Type:{1} ", (long)i, i->ObjectType)); GetStackObjectText(sb, i, mStack, valuePointerEnd); if (i < esp) { if (i->ObjectType == ObjectTypes.ValueTypeObjectReference) VisitValueTypeReference(*(StackObject**)&i->Value, leakVObj); } if (isLocal) { sb.Append(string.Format("|Loc:{0}", localIdx)); if (localIdx == 0) { sb.Append(" Method:"); sb.Append(localMethod.ToString()); } } if (isBase) { sb.Append("|Base"); sb.Append(" Method:"); sb.Append(baseMethod.ToString()); } System.Diagnostics.Debug.Print(sb.ToString()); } for (var i = stack.ValueTypeStackBase; i > stack.ValueTypeStackPointer;) { var vt = domain.GetType(i->Value); var cnt = i->ValueLow; bool leak = leakVObj.Contains((long)i); System.Diagnostics.Debug.Print("----------------------------------------------"); System.Diagnostics.Debug.Print(string.Format("{2}(0x{0:X8}){1}", (long)i, vt, leak ? "*" : "")); for (int j = 0; j < cnt; j++) { StringBuilder sb = new StringBuilder(); var ptr = Minus(i, j + 1); sb.Append(string.Format("(0x{0:X8}) Type:{1} ", (long)ptr, ptr->ObjectType)); GetStackObjectText(sb, ptr, mStack, valuePointerEnd); System.Diagnostics.Debug.Print(sb.ToString()); } i = Minus(i, i->ValueLow + 1); } System.Diagnostics.Debug.Print("Managed Objects:"); for (int i = 0; i < mStack.Count; i++) { System.Diagnostics.Debug.Print(string.Format("({0}){1}", i, mStack[i])); } #endif } unsafe void GetStackObjectText(StringBuilder sb, StackObject* esp, IList mStack, StackObject* valueTypeEnd) { string text = "null"; switch (esp->ObjectType) { case ObjectTypes.StackObjectReference: { sb.Append(string.Format("Value:0x{0:X8}", (long)*(StackObject**)&esp->Value)); } break; case ObjectTypes.ValueTypeObjectReference: { object obj = null; var dst = *(StackObject**)&esp->Value; if (dst > valueTypeEnd) obj = StackObject.ToObject(esp, domain, mStack); if (obj != null) text = obj.ToString(); text += string.Format("({0})", domain.GetType(dst->Value)); } sb.Append(string.Format("Value:0x{0:X8} Text:{1} ", (long)*(StackObject**)&esp->Value, text)); break; default: { if (esp->ObjectType >= ObjectTypes.Null && esp->ObjectType <= ObjectTypes.ArrayReference) { if (esp->ObjectType < ObjectTypes.Object || esp->Value < mStack.Count) { var obj = StackObject.ToObject(esp, domain, mStack); if (obj != null) text = obj.ToString(); } } sb.Append(string.Format("Value:{0} ValueLow:{1} Text:{2} ", esp->Value, esp->ValueLow, text)); } break; } } unsafe void VisitValueTypeReference(StackObject* esp, HashSet leak) { leak.Remove((long)esp); for (int i = 0; i < esp->ValueLow; i++) { var ptr = Minus(esp, i + 1); if (ptr->ObjectType == ObjectTypes.ValueTypeObjectReference) { VisitValueTypeReference(*(StackObject**)&ptr->Value, leak); } } } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/DebugSocket.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Net.Sockets; namespace ILRuntime.Runtime.Debugger { public class DebugSocket { private Socket _socket = null; private bool _ready = false; bool connectFailed = false; private const int MAX_BUFF_SIZE = 256 * 1024; private const int HEAD_SIZE = 8; private byte[] _headBuffer = new byte[HEAD_SIZE]; private byte[] _sendBuffer = new byte[64 * 1024]; //private MemoryPoolSafe _packagePool = new MemoryPoolSafe(); //private Package _currPackage = null; private System.IO.MemoryStream _sendStream = null; BinaryWriter bw; const int RECV_BUFFER_SIZE = 1024; private MemoryStream recvBuffer = new MemoryStream(); private int lastMsgLength = -1; private byte[] socketAsyncBuffer = new byte[RECV_BUFFER_SIZE]; private SocketAsyncEventArgs saeArgs; private object socketLockObj = new object(); private byte[] _sendHeaderBuffer = new byte[HEAD_SIZE]; public bool Disconnected { get { return _socket == null || !_socket.Connected; } } public Action OnConnect { get; set; } public Action OnConnectFailed { get; set; } public Action OnClose { get; set; } public Action OnReciveMessage { get; set; } public DebugSocket() { _sendStream = new System.IO.MemoryStream(_sendBuffer); bw = new BinaryWriter(_sendStream); } public DebugSocket(Socket _socket) : this() { this._socket = _socket; BeginReceive(); _ready = true; } public void Connect(string ip, int port) { Close(); Socket socket; socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.BeginConnect(ip, port, new AsyncCallback(onConnected), this); _socket = socket; _ready = false; } private void AsyncRecv_Completed(object sender, SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success && e.BytesTransferred > 0) { try { ReceivePayload(e.Buffer, e.BytesTransferred); } catch (Exception ex) { Close(); return; } } else { Close(); return; } try { //继续接受数据 if (!_socket.ReceiveAsync(saeArgs)) { AsyncRecv_Completed(null, saeArgs); } } catch (Exception ex) { Close(); throw ex; } } private void ReceivePayload(byte[] data, int length) { if (_socket == null) return; if (!_socket.Connected) { Close(); return; } //接受数据并拼接成message byte[] msgBuff; //写入缓存 recvBuffer.Position = recvBuffer.Length; recvBuffer.Write(data, 0, length); //如果长度有错,返回 if (lastMsgLength < 0 && recvBuffer.Length < 4) { msgBuff = null; return; } recvBuffer.Position = 0; BinaryReader br = new BinaryReader(recvBuffer); //读取消息长度 if (lastMsgLength < 0) { lastMsgLength = br.ReadInt32() - 4; if (lastMsgLength > MAX_BUFF_SIZE) { Close(); throw new Exception("Too long package length!"); } } int remaining = (int)(recvBuffer.Length - recvBuffer.Position); //消息已经完整 while (remaining >= lastMsgLength && lastMsgLength > 0) { //读取一条消息 int type = br.ReadInt32(); msgBuff = br.ReadBytes(lastMsgLength - 4); if (OnReciveMessage != null) OnReciveMessage((DebugMessageType)type, msgBuff); lastMsgLength = -1; remaining = (int)(recvBuffer.Length - recvBuffer.Position); //保留剩余数据 if (remaining >= 4) { lastMsgLength = br.ReadInt32() - 4; remaining -= 4; if (lastMsgLength > MAX_BUFF_SIZE) { Close(); throw new Exception("Too long package length!"); } } } remaining = (int)(recvBuffer.Length - recvBuffer.Position); if (remaining > 0) { byte[] buffer = recvBuffer.GetBuffer(); Array.Copy(buffer, recvBuffer.Position, buffer, 0, remaining); } recvBuffer.Position = 0; recvBuffer.SetLength(remaining); } private void onConnected(IAsyncResult result) { if (_socket.Connected) { _socket.EndConnect(result); BeginReceive(); if (OnConnect != null) OnConnect(); //ReceiveOnce(); } else { if (OnConnectFailed != null) OnConnectFailed(); } } void BeginReceive() { saeArgs = new SocketAsyncEventArgs(); saeArgs.Completed += AsyncRecv_Completed; saeArgs.SetBuffer(socketAsyncBuffer, 0, socketAsyncBuffer.Length); _socket.ReceiveAsync(saeArgs); _ready = true; } //len type msg public void Send(DebugMessageType type, byte[] buffer, int len) { if (!_ready) return; //timeStamp = UnityEngine.Time.realtimeSinceStartup; _sendStream.Position = 0; bw.Write(len + HEAD_SIZE); bw.Write((int)type); bw.Write(buffer, 0, len); int totalLen = (int)_sendStream.Position; RawSend(_socket, _sendBuffer, totalLen); //_socket.Send(_sendBuffer, len, SocketFlags.None); } private void RawSend(Socket sock, byte[] buf, int end) { if (sock == null) return; if (end < 0) end = buf.Length; sock.Send(buf, end, SocketFlags.None); } public void Close() { if (_socket == null || !_ready) return; if (saeArgs != null) saeArgs.Dispose(); _socket.Close(); _socket = null; _ready = false; if (OnClose != null) { OnClose(); } } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/DebuggerServer/DebuggerServer.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Net.Sockets; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.Runtime.Debugger.Protocol; namespace ILRuntime.Runtime.Debugger { public class DebuggerServer { public const int Version = 1; TcpListener listener; //HashSet> clients = new HashSet>(); bool isUp = false; int maxNewConnections = 1; int port; Thread mainLoop; DebugSocket clientSocket; System.IO.MemoryStream sendStream = new System.IO.MemoryStream(64 * 1024); System.IO.BinaryWriter bw; DebugService ds; /// /// 服务器监听的端口 /// public int Port { get { return port; } set { this.port = value; } } public DebugSocket Client { get { return clientSocket; } } public bool IsAttached { get { return clientSocket != null && !clientSocket.Disconnected; } } public DebuggerServer(DebugService ds) { this.ds = ds; bw = new System.IO.BinaryWriter(sendStream); } public virtual bool Start() { mainLoop = new Thread(new ThreadStart(this.NetworkLoop)); mainLoop.Start(); this.listener = new TcpListener(port); try { listener.Start(); } catch { return false; } isUp = true; return true; } public virtual void Stop() { isUp = false; if (this.listener != null) this.listener.Stop(); mainLoop.Abort(); mainLoop = null; } void NetworkLoop() { while (true) { try { // let new clients (max 10) connect if (isUp && clientSocket == null) { for (int i = 0; listener.Pending() && i < maxNewConnections; i++) { CreateNewSession(listener); } } System.Threading.Thread.Sleep(1); } catch (ThreadAbortException) { } catch (Exception) { } } } void CreateNewSession(TcpListener listener) { Socket sock = listener.AcceptSocket(); clientSocket = new DebugSocket(sock); clientSocket.OnReciveMessage = OnReceive; clientSocket.OnClose = OnClose; ClientConnected(); } void ClientConnected() { } void OnClose() { ds.Detach(); clientSocket = null; } void OnReceive(DebugMessageType type, byte[] buffer) { if (clientSocket == null || clientSocket.Disconnected) return; System.IO.MemoryStream ms = new System.IO.MemoryStream(buffer); System.IO.BinaryReader br = new System.IO.BinaryReader(ms); switch (type) { case DebugMessageType.CSAttach: { SendAttachResult(); } break; case DebugMessageType.CSBindBreakpoint: { CSBindBreakpoint msg = new Protocol.CSBindBreakpoint(); msg.BreakpointHashCode = br.ReadInt32(); msg.TypeName = br.ReadString(); msg.MethodName = br.ReadString(); msg.StartLine = br.ReadInt32(); msg.EndLine = br.ReadInt32(); TryBindBreakpoint(msg); } break; case DebugMessageType.CSDeleteBreakpoint: { CSDeleteBreakpoint msg = new Protocol.CSDeleteBreakpoint(); msg.BreakpointHashCode = br.ReadInt32(); ds.DeleteBreakpoint(msg.BreakpointHashCode); } break; case DebugMessageType.CSExecute: { CSExecute msg = new Protocol.CSExecute(); msg.ThreadHashCode = br.ReadInt32(); ds.ExecuteThread(msg.ThreadHashCode); } break; case DebugMessageType.CSStep: { CSStep msg = new CSStep(); msg.ThreadHashCode = br.ReadInt32(); msg.StepType = (StepTypes)br.ReadByte(); ds.StepThread(msg.ThreadHashCode, msg.StepType); } break; case DebugMessageType.CSResolveVariable: { CSResolveVariable msg = new CSResolveVariable(); msg.Name = br.ReadString(); msg.Parent = ReadVariableReference(br); var info = ds.ResolveVariable(msg.Parent, msg.Name); } break; } } VariableReference ReadVariableReference(System.IO.BinaryReader br) { VariableReference res = null; if (br.ReadBoolean()) { res = new Debugger.VariableReference(); res.Address = br.ReadInt64(); res.Type = (VariableTypes)br.ReadByte(); res.Offset = br.ReadInt32(); res.Parent = ReadVariableReference(br); } return res; } void SendAttachResult() { sendStream.Position = 0; bw.Write((byte)AttachResults.OK); bw.Write(Version); DoSend(DebugMessageType.SCAttachResult); lock (ds.AppDomain.FreeIntepreters) { foreach (var i in ds.AppDomain.Intepreters) { SendSCThreadStarted(i.Key); } } } void DoSend(DebugMessageType type) { if (clientSocket != null && !clientSocket.Disconnected) clientSocket.Send(type, sendStream.GetBuffer(), (int)sendStream.Position); } void TryBindBreakpoint(CSBindBreakpoint msg) { var domain = ds.AppDomain; SCBindBreakpointResult res = new Protocol.SCBindBreakpointResult(); res.BreakpointHashCode = msg.BreakpointHashCode; IType type; if (domain.LoadedTypes.TryGetValue(msg.TypeName, out type)) { if(type is ILType) { ILType it = (ILType)type; ILMethod found = null; foreach(var i in it.GetMethods()) { if(i.Name == msg.MethodName) { ILMethod ilm = (ILMethod)i; if (ilm.StartLine <= (msg.StartLine + 1) && ilm.EndLine >= (msg.StartLine + 1)) { found = ilm; break; } } } if(found != null) { ds.SetBreakPoint(found.GetHashCode(), msg.BreakpointHashCode, msg.StartLine); res.Result = BindBreakpointResults.OK; } else { res.Result = BindBreakpointResults.CodeNotFound; } } else { res.Result = BindBreakpointResults.TypeNotFound; } } else { res.Result = BindBreakpointResults.TypeNotFound; } SendSCBindBreakpointResult(res); } void SendSCBindBreakpointResult(SCBindBreakpointResult msg) { sendStream.Position = 0; bw.Write(msg.BreakpointHashCode); bw.Write((byte)msg.Result); DoSend(DebugMessageType.SCBindBreakpointResult); } internal void SendSCBreakpointHit(int intpHash, int bpHash, KeyValuePair[] info) { sendStream.Position = 0; bw.Write(bpHash); bw.Write(intpHash); WriteStackFrames(info); DoSend(DebugMessageType.SCBreakpointHit); } internal void SendSCStepComplete(int intpHash, KeyValuePair[] info) { sendStream.Position = 0; bw.Write(intpHash); WriteStackFrames(info); DoSend(DebugMessageType.SCStepComplete); } void SendSCResolveVariableResult(VariableInfo info) { sendStream.Position = 0; WriteVariableInfo(info); DoSend(DebugMessageType.SCResolveVariableResult); } void WriteStackFrames(KeyValuePair[] info) { bw.Write(info.Length); foreach (var i in info) { bw.Write(i.Key); bw.Write(i.Value.Length); foreach (var j in i.Value) { bw.Write(j.MethodName); bw.Write(j.DocumentName); bw.Write(j.StartLine); bw.Write(j.StartColumn); bw.Write(j.EndLine); bw.Write(j.EndColumn); bw.Write(j.LocalVariables.Length); foreach (var k in j.LocalVariables) { WriteVariableInfo(k); } } } } void WriteVariableInfo(VariableInfo k) { bw.Write(k.Address); bw.Write((byte)k.Type); bw.Write(k.Offset); bw.Write(k.Name); bw.Write(k.Value); bw.Write(k.TypeName); bw.Write(k.Expandable); } internal void SendSCThreadStarted(int threadHash) { sendStream.Position = 0; bw.Write(threadHash); DoSend(DebugMessageType.SCThreadStarted); } internal void SendSCThreadEnded(int threadHash) { sendStream.Position = 0; bw.Write(threadHash); DoSend(DebugMessageType.SCThreadEnded); } public void NotifyModuleLoaded(string modulename) { sendStream.Position = 0; bw.Write(modulename); DoSend(DebugMessageType.SCModuleLoaded); } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/Protocol/CSBindBreakpoint.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class CSBindBreakpoint { public int BreakpointHashCode { get; set; } public string TypeName { get; set; } public string MethodName { get; set; } public int StartLine { get; set; } public int EndLine { get; set; } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/Protocol/CSDeleteBreakpoint.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class CSDeleteBreakpoint { public int BreakpointHashCode { get; set; } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/Protocol/CSExecute.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class CSExecute { public int ThreadHashCode { get; set; } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/Protocol/CSResolveVariable.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class CSResolveVariable { public string Name { get; set; } public VariableReference Parent { get; set; } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/Protocol/CSStep.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class CSStep { public int ThreadHashCode { get; set; } public StepTypes StepType { get; set; } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/Protocol/SCAttachResult.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public enum AttachResults { OK, AlreadyAttached, } public class SCAttachResult { public AttachResults Result { get; set; } public int DebugServerVersion { get; set; } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/Protocol/SCBindBreakpointResult.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public enum BindBreakpointResults { OK, TypeNotFound, CodeNotFound, } public class SCBindBreakpointResult { public int BreakpointHashCode { get; set; } public BindBreakpointResults Result { get; set; } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/Protocol/SCBreakpointHit.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class SCBreakpointHit { public int BreakpointHashCode { get; set; } public int ThreadHashCode { get; set; } public KeyValuePair[] StackFrame { get; set; } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/Protocol/SCModuleLoaded.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class SCModuleLoaded { public string ModuleName { get; set; } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/Protocol/SCResolveVariableResult.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class SCResolveVariableResult { public VariableInfo Info { get; set; } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/Protocol/SCStepComplete.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class SCStepComplete { public int ThreadHashCode { get; set; } public KeyValuePair[] StackFrame { get; set; } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/Protocol/SCThreadStarted.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger.Protocol { public class SCThreadStarted { public int ThreadHashCode { get; set; } } public class SCThreadEnded { public int ThreadHashCode { get; set; } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/StackFrameInfo.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger { public class StackFrameInfo { public string MethodName { get; set; } public string DocumentName { get; set; } public int StartLine { get; set; } public int StartColumn { get; set; } public int EndLine { get; set; } public int EndColumn { get; set; } public VariableInfo[] LocalVariables { get; set; } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/StepTypes.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger { public enum StepTypes { None, Into, Over, Out, } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Debugger/VariableInfo.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Debugger { public enum VariableTypes { Normal, FieldReference, Error, } public class VariableReference { public long Address { get; set; } public VariableTypes Type { get; set; } public int Offset { get; set; } public VariableReference Parent { get; set; } } public class VariableInfo { public long Address { get; set; } public VariableTypes Type { get; set; } public string Name { get; set; } public string TypeName { get; set; } public string Value { get; set; } public bool Expandable { get; set; } public int Offset { get; set;} } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Enviorment/AppDomain.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using Mono.Cecil; using System.Reflection; using Mono.Cecil.Cil; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.CLR.Utils; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Debugger; using ILRuntime.Runtime.Stack; using ILRuntime.Other; namespace ILRuntime.Runtime.Enviorment { public unsafe delegate StackObject* CLRRedirectionDelegate(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj); public delegate object CLRFieldGetterDelegate(ref object target); public delegate void CLRFieldSetterDelegate(ref object target, object value); public delegate object CLRMemberwiseCloneDelegate(ref object target); public delegate object CLRCreateDefaultInstanceDelegate(); public delegate object CLRCreateArrayInstanceDelegate(int size); public class AppDomain { Queue freeIntepreters = new Queue(); Dictionary intepreters = new Dictionary(); Dictionary crossAdaptors = new Dictionary(new ByReferenceKeyComparer()); Dictionary valueTypeBinders = new Dictionary(); ThreadSafeDictionary mapType = new ThreadSafeDictionary(); Dictionary clrTypeMapping = new Dictionary(new ByReferenceKeyComparer()); ThreadSafeDictionary mapTypeToken = new ThreadSafeDictionary(); ThreadSafeDictionary mapMethod = new ThreadSafeDictionary(); ThreadSafeDictionary mapString = new ThreadSafeDictionary(); Dictionary redirectMap = new Dictionary(); Dictionary fieldGetterMap = new Dictionary(); Dictionary fieldSetterMap = new Dictionary(); Dictionary memberwiseCloneMap = new Dictionary(new ByReferenceKeyComparer()); Dictionary createDefaultInstanceMap = new Dictionary(new ByReferenceKeyComparer()); Dictionary createArrayInstanceMap = new Dictionary(new ByReferenceKeyComparer()); IType voidType, intType, longType, boolType, floatType, doubleType, objectType; DelegateManager dMgr; Assembly[] loadedAssemblies; Dictionary references = new Dictionary(); DebugService debugService; /// /// Determine if invoking unbinded CLR method(using reflection) is allowed /// public bool AllowUnboundCLRMethod { get; set; } #if UNITY_EDITOR public int UnityMainThreadID { get; set; } #endif public unsafe AppDomain() { AllowUnboundCLRMethod = true; loadedAssemblies = System.AppDomain.CurrentDomain.GetAssemblies(); var mi = typeof(System.Runtime.CompilerServices.RuntimeHelpers).GetMethod("InitializeArray"); RegisterCLRMethodRedirection(mi, CLRRedirections.InitializeArray); foreach (var i in typeof(System.Activator).GetMethods()) { if (i.Name == "CreateInstance" && i.IsGenericMethodDefinition) { RegisterCLRMethodRedirection(i, CLRRedirections.CreateInstance); } else if(i.Name == "CreateInstance" && i.GetParameters().Length == 1) { RegisterCLRMethodRedirection(i, CLRRedirections.CreateInstance2); } } foreach (var i in typeof(System.Type).GetMethods()) { if (i.Name == "GetType" && i.IsStatic) { RegisterCLRMethodRedirection(i, CLRRedirections.GetType); } if(i.Name=="Equals" && i.GetParameters()[0].ParameterType == typeof(Type)) { RegisterCLRMethodRedirection(i, CLRRedirections.TypeEquals); } } foreach (var i in typeof(System.Delegate).GetMethods()) { if (i.Name == "Combine" && i.GetParameters().Length == 2) { RegisterCLRMethodRedirection(i, CLRRedirections.DelegateCombine); } if(i.Name == "Remove") { RegisterCLRMethodRedirection(i, CLRRedirections.DelegateRemove); } if(i.Name == "op_Equality") { RegisterCLRMethodRedirection(i, CLRRedirections.DelegateEqulity); } if(i.Name == "op_Inequality") { RegisterCLRMethodRedirection(i, CLRRedirections.DelegateInequlity); } } foreach(var i in typeof(MethodBase).GetMethods()) { if(i.Name == "Invoke" && i.GetParameters().Length == 2) { RegisterCLRMethodRedirection(i, CLRRedirections.MethodInfoInvoke); } } mi = typeof(System.Type).GetMethod("GetTypeFromHandle"); RegisterCLRMethodRedirection(mi, CLRRedirections.GetTypeFromHandle); mi = typeof(object).GetMethod("GetType"); RegisterCLRMethodRedirection(mi, CLRRedirections.ObjectGetType); dMgr = new DelegateManager(this); dMgr.RegisterDelegateConvertor((dele) => { return dele; }); RegisterCrossBindingAdaptor(new Adaptors.AttributeAdaptor()); debugService = new Debugger.DebugService(this); } public IType VoidType { get { return voidType; } } public IType IntType { get { return intType; } } public IType LongType { get { return longType; } } public IType BoolType { get { return boolType; } } public IType FloatType { get { return floatType; } } public IType DoubleType { get { return doubleType; } } public IType ObjectType { get { return objectType; } } /// /// Attention, this property isn't thread safe /// public Dictionary LoadedTypes { get { return mapType.InnerDictionary; } } internal Dictionary RedirectMap { get { return redirectMap; } } internal Dictionary FieldGetterMap { get { return fieldGetterMap; } } internal Dictionary FieldSetterMap { get { return fieldSetterMap; } } internal Dictionary MemberwiseCloneMap { get { return memberwiseCloneMap; } } internal Dictionary CreateDefaultInstanceMap { get { return createDefaultInstanceMap; } } internal Dictionary CreateArrayInstanceMap { get { return createArrayInstanceMap; } } internal Dictionary CrossBindingAdaptors { get { return crossAdaptors; } } internal Dictionary ValueTypeBinders { get { return valueTypeBinders; } } public DebugService DebugService { get { return debugService; } } internal Dictionary Intepreters { get { return intepreters; } } internal Queue FreeIntepreters { get { return freeIntepreters; } } public DelegateManager DelegateManager { get { return dMgr; } } /// /// 加载Assembly 文件,从指定的路径 /// /// 路径 public void LoadAssemblyFile(string path) { FileInfo file = new FileInfo(path); if (!file.Exists) { throw new FileNotFoundException(string.Format("Assembly File not find!:\r\n{0}", path)); } else { using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) { LoadAssembly(fs); fs.Dispose(); } } } #if USE_MDB || USE_PDB /// /// 加载Assembly 文件和PDB文件或MDB文件,从指定的路径(PDB和MDB文件按默认命名方式,并且和Assembly文件处于同一目录中 /// /// 路径 public void LoadAssemblyFileAndSymbol(string path) { FileInfo file = new FileInfo(path); if (!file.Exists) { throw new FileNotFoundException(string.Format("Assembly File not find!:\r\n{0}", path)); } else { var dlldir = file.DirectoryName; var assname = Path.GetFileNameWithoutExtension(file.Name); var pdbpath = string.Format("{0}/{1}.pdb",dlldir,assname); var mdbpath = string.Format("{0}/{1}.mdb", dlldir, assname); string symbolPath = ""; bool isPDB = true; if (File.Exists(pdbpath)) { symbolPath = pdbpath; } else if (File.Exists(mdbpath)) { symbolPath = mdbpath; isPDB = false; } if (string.IsNullOrEmpty(symbolPath)) { throw new FileNotFoundException(string.Format("symbol file not find!:\r\ncheck:\r\n{0}\r\n{1}\r\n", pdbpath,mdbpath)); } using (FileStream fs = new FileStream(file.FullName, FileMode.Open, FileAccess.Read)) { using (var pdbfs = new System.IO.FileStream(symbolPath, FileMode.Open)) { if (isPDB) { LoadAssemblyPDB(fs, pdbfs); } else { LoadAssemblyMDB(fs, pdbfs); } } } } } #endif #if USE_PDB /// /// 加载Assembly 文件和PDB文件,两者都从指定的路径 /// /// Assembly 文件路径 /// symbol文件路径 public void LoadAssemblyFileAndPDB(string assemblyFilePath,string symbolFilePath) { FileInfo assfile = new FileInfo(assemblyFilePath); FileInfo pdbfile = new FileInfo(symbolFilePath); if (!assfile.Exists) { throw new FileNotFoundException(string.Format("Assembly File not find!:\r\n{0}", assemblyFilePath)); } if (!pdbfile.Exists) { throw new FileNotFoundException(string.Format("symbol file not find!:\r\n{0}", symbolFilePath)); } using (FileStream fs = new FileStream(assfile.FullName, FileMode.Open, FileAccess.Read)) { using (var pdbfs = new System.IO.FileStream(pdbfile.FullName, FileMode.Open)) { LoadAssemblyPDB(fs, pdbfs); } } } /// /// 从流加载Assembly,以及symbol符号文件(pdb) /// /// Assembly Stream /// PDB Stream public void LoadAssemblyPDB(System.IO.Stream stream, System.IO.Stream symbol) { LoadAssembly(stream, symbol, new Mono.Cecil.Pdb.PdbReaderProvider()); } #endif #if USE_MDB /// /// 加载Assembly 文件和MDB文件,两者都从指定的路径 /// /// Assembly 文件路径 /// symbol文件路径 public void LoadAssemblyFileAndMDB(string assemblyFilePath, string symbolFilePath) { FileInfo assfile = new FileInfo(assemblyFilePath); FileInfo pdbfile = new FileInfo(symbolFilePath); if (!assfile.Exists) { throw new FileNotFoundException(string.Format("Assembly File not find!:\r\n{0}", assemblyFilePath)); } if (!pdbfile.Exists) { throw new FileNotFoundException(string.Format("symbol file not find!:\r\n{0}", symbolFilePath)); } using (FileStream fs = new FileStream(assfile.FullName, FileMode.Open, FileAccess.Read)) { using (var pdbfs = new System.IO.FileStream(pdbfile.FullName, FileMode.Open)) { LoadAssemblyMDB(fs, pdbfs); } } } /// /// 从流加载Assembly,以及symbol符号文件(Mdb) /// /// Assembly Stream /// PDB Stream public void LoadAssemblyMDB(System.IO.Stream stream, System.IO.Stream symbol) { LoadAssembly(stream, symbol, new Mono.Cecil.Mdb.MdbReaderProvider()); } #endif /// /// 从流加载Assembly 不加载symbol符号文件 /// /// Dll数据流 public void LoadAssembly(System.IO.Stream stream) { LoadAssembly(stream, null, null); } /// /// 从流加载Assembly,以及symbol符号文件(pdb) /// /// Assembly Stream /// symbol Stream /// symbol 读取器 public void LoadAssembly(System.IO.Stream stream, System.IO.Stream symbol, ISymbolReaderProvider symbolReader) { var module = ModuleDefinition.ReadModule(stream); //从MONO中加载模块 if (symbolReader != null && symbol != null) { module.ReadSymbols(symbolReader.GetSymbolReader(module, symbol)); //加载符号表 } if (module.HasAssemblyReferences) //如果此模块引用了其他模块 { foreach (var ar in module.AssemblyReferences) { /*if (moduleref.Contains(ar.Name) == false) moduleref.Add(ar.Name); if (moduleref.Contains(ar.FullName) == false) moduleref.Add(ar.FullName);*/ } } if (module.HasTypes) { List types = new List(); foreach (var t in module.GetTypes()) //获取所有此模块定义的类型 { ILType type = new ILType(t, this); mapType[t.FullName] = type; types.Add(type); } } if (voidType == null) { voidType = GetType("System.Void"); intType = GetType("System.Int32"); longType = GetType("System.Int64"); boolType = GetType("System.Boolean"); floatType = GetType("System.Single"); doubleType = GetType("System.Double"); objectType = GetType("System.Object"); } module.AssemblyResolver.ResolveFailure += AssemblyResolver_ResolveFailure; #if DEBUG debugService.NotifyModuleLoaded(module.Name); #endif } /// /// External reference should be added to the AppDomain by the method /// /// Assembly name, without .dll /// file content public void AddReferenceBytes(string name, byte[] content) { references[name] = content; } private AssemblyDefinition AssemblyResolver_ResolveFailure(object sender, AssemblyNameReference reference) { byte[] content; if (references.TryGetValue(reference.Name, out content)) { using (System.IO.MemoryStream ms = new System.IO.MemoryStream(content)) { return AssemblyDefinition.ReadAssembly(ms); } } else return null; } public void RegisterCLRMethodRedirection(MethodBase mi, CLRRedirectionDelegate func) { if (!redirectMap.ContainsKey(mi)) redirectMap[mi] = func; } public void RegisterCLRFieldGetter(FieldInfo f, CLRFieldGetterDelegate getter) { if (!fieldGetterMap.ContainsKey(f)) fieldGetterMap[f] = getter; } public void RegisterCLRFieldSetter(FieldInfo f, CLRFieldSetterDelegate setter) { if (!fieldSetterMap.ContainsKey(f)) fieldSetterMap[f] = setter; } public void RegisterCLRMemberwiseClone(Type t, CLRMemberwiseCloneDelegate memberwiseClone) { if (!memberwiseCloneMap.ContainsKey(t)) memberwiseCloneMap[t] = memberwiseClone; } public void RegisterCLRCreateDefaultInstance(Type t, CLRCreateDefaultInstanceDelegate createDefaultInstance) { if (!createDefaultInstanceMap.ContainsKey(t)) createDefaultInstanceMap[t] = createDefaultInstance; } public void RegisterCLRCreateArrayInstance(Type t, CLRCreateArrayInstanceDelegate createArray) { if (!createArrayInstanceMap.ContainsKey(t)) createArrayInstanceMap[t] = createArray; } public void RegisterValueTypeBinder(Type t, ValueTypeBinder binder) { if (!valueTypeBinders.ContainsKey(t)) { valueTypeBinders[t] = binder; binder.RegisterCLRRedirection(this); } } /// /// 更近类型名称返回类型 /// /// 类型全名 命名空间.类型名 /// public IType GetType(string fullname) { IType res; if (fullname == null) { return null; } if (mapType.TryGetValue(fullname, out res)) return res; string baseType; List genericParams; bool isArray; ParseGenericType(fullname, out baseType, out genericParams, out isArray); bool isByRef = baseType.EndsWith("&"); if (isByRef) baseType = baseType.Substring(0, baseType.Length - 1); if (genericParams != null || isArray || isByRef) { IType bt = GetType(baseType); if (bt == null) { bt = GetType(baseType.Replace("/", "+")); } if (bt == null) return null; if (genericParams != null) { KeyValuePair[] genericArguments = new KeyValuePair[genericParams.Count]; for (int i = 0; i < genericArguments.Length; i++) { string key = "!" + i; IType val = GetType(genericParams[i]); if (val == null) return null; genericArguments[i] = new KeyValuePair(key, val); } bt = bt.MakeGenericInstance(genericArguments); mapType[bt.FullName] = bt; mapTypeToken[bt.GetHashCode()] = bt; StringBuilder sb = new StringBuilder(); sb.Append(baseType); sb.Append('<'); for (int i = 0; i < genericParams.Count; i++) { if (i > 0) sb.Append(","); if (genericParams[i].Contains(",")) sb.Append(genericParams[i].Substring(0, genericParams[i].IndexOf(','))); else sb.Append(genericParams[i]); } sb.Append('>'); var asmName = sb.ToString(); if (bt.FullName != asmName) mapType[asmName] = bt; } if (isArray) { bt = bt.MakeArrayType(); mapType[bt.FullName] = bt; mapTypeToken[bt.GetHashCode()] = bt; if (!isByRef) { mapType[fullname] = bt; return bt; } } if (isByRef) { res = bt.MakeByRefType(); mapType[fullname] = res; mapType[res.FullName] = res; mapTypeToken[res.GetHashCode()] = res; return res; } else { mapType[fullname] = bt; return bt; } } else { Type t = Type.GetType(fullname); if (t != null) { if (!clrTypeMapping.TryGetValue(t, out res)) { res = new CLRType(t, this); clrTypeMapping[t] = res; } mapType[fullname] = res; mapType[res.FullName] = res; mapType[t.AssemblyQualifiedName] = res; mapTypeToken[res.GetHashCode()] = res; return res; } } return null; } internal static void ParseGenericType(string fullname, out string baseType, out List genericParams, out bool isArray) { StringBuilder sb = new StringBuilder(); int depth = 0; baseType = ""; genericParams = null; if (fullname.Length >2 && fullname.Substring(fullname.Length - 2) == "[]") { fullname = fullname.Substring(0, fullname.Length - 2); isArray = true; } else isArray = false; if (fullname.Contains('<') || fullname.Contains('[')) { foreach (var i in fullname) { if (i == '<' || i == '[') { depth++; if (depth == 1) { baseType = sb.ToString(); sb.Length = 0; genericParams = new List(); continue; } } if (i == ',' && depth == 1) { string name = sb.ToString(); if (name.StartsWith("[")) name = name.Substring(1, name.Length - 2); if (!string.IsNullOrEmpty(name)) genericParams.Add(name); sb.Length = 0; continue; } if (i == '>' || i == ']') { depth--; if (depth == 0) { string name = sb.ToString(); if (name.StartsWith("[")) name = name.Substring(1, name.Length - 2); if (!string.IsNullOrEmpty(name)) genericParams.Add(name); else { if (!isArray) { isArray = true; } else { baseType += "[]"; } } sb.Length = 0; continue; } } sb.Append(i); } if (sb.Length > 0) { baseType += sb.ToString(); } if (genericParams != null && genericParams.Count == 0) genericParams = null; } else baseType = fullname; } string GetAssemblyName(IMetadataScope scope) { return scope is AssemblyNameReference ? ((AssemblyNameReference)scope).FullName : null; } internal IType GetType(object token, IType contextType, IMethod contextMethod) { int hash = token.GetHashCode(); IType res; if (mapTypeToken.TryGetValue(hash, out res)) return res; Mono.Cecil.ModuleDefinition module = null; KeyValuePair[] genericArguments = null; string typename = null; string scope = null; bool dummyGenericInstance = false; if (token is Mono.Cecil.TypeDefinition) { Mono.Cecil.TypeDefinition _def = (token as Mono.Cecil.TypeDefinition); module = _def.Module; typename = _def.FullName; scope = GetAssemblyName(_def.Scope); } else if (token is Mono.Cecil.TypeReference) { Mono.Cecil.TypeReference _ref = (token as Mono.Cecil.TypeReference); if (_ref.IsGenericParameter) { IType t = null; if (contextType != null) { t = contextType.FindGenericArgument(_ref.Name); } if (t == null && contextMethod != null && contextMethod is ILMethod) { t = ((ILMethod)contextMethod).FindGenericArgument(_ref.Name); } return t; } if (_ref.IsByReference) { var et = _ref.GetElementType(); bool valid = !et.IsGenericParameter; var t = GetType(et, contextType, contextMethod); if (t != null) { res = t.MakeByRefType(); if (res is ILType && valid) { ///Unify the TypeReference ((ILType)res).TypeReference = _ref; } if (valid) mapTypeToken[hash] = res; if (!string.IsNullOrEmpty(res.FullName)) mapType[res.FullName] = res; return res; } return null; } if (_ref.IsArray) { var t = GetType(_ref.GetElementType(), contextType, contextMethod); if (t != null) { res = t.MakeArrayType(); if (res is ILType) { ///Unify the TypeReference ((ILType)res).TypeReference = _ref; } mapTypeToken[hash] = res; if (!string.IsNullOrEmpty(res.FullName)) mapType[res.FullName] = res; return res; } return t; } module = _ref.Module; if (_ref.IsGenericInstance) { GenericInstanceType gType = (GenericInstanceType)_ref; typename = gType.ElementType.FullName; scope = GetAssemblyName(gType.ElementType.Scope); TypeReference tr = gType.ElementType; genericArguments = new KeyValuePair[gType.GenericArguments.Count]; for (int i = 0; i < genericArguments.Length; i++) { string key = tr.GenericParameters[i].Name; IType val; if (gType.GenericArguments[i].IsGenericParameter) { val = contextType.FindGenericArgument(gType.GenericArguments[i].Name); dummyGenericInstance = true; if (val == null) { if (contextMethod != null && contextMethod is ILMethod) { val = ((ILMethod)contextMethod).FindGenericArgument(gType.GenericArguments[i].Name); } else return null; } } else val = GetType(gType.GenericArguments[i], contextType, contextMethod); if (val != null && val.HasGenericParameter) dummyGenericInstance = true; if (val != null) genericArguments[i] = new KeyValuePair(key, val); else { genericArguments = null; break; } } } else { typename = _ref.FullName; scope = GetAssemblyName(_ref.Scope); } } else { throw new NotImplementedException(); } res = GetType(typename); if (res == null) { typename = typename.Replace("/", "+"); res = GetType(typename); } if (res == null && scope != null) res = GetType(typename + ", " + scope); if (res == null) { if (scope != null) { string aname = scope.Split(',')[0]; foreach (var i in loadedAssemblies) { if (aname == i.GetName().Name) { res = GetType(typename + ", " + i.FullName); if (res != null) break; } } } if (res == null) { foreach (var j in loadedAssemblies) { res = GetType(typename + ", " + j.FullName); if (res != null) break; } } if (res != null && scope != null) { mapType[typename + ", " + scope] = res; } } if (res == null) throw new KeyNotFoundException("Cannot find Type:" + typename); if (genericArguments != null) { res = res.MakeGenericInstance(genericArguments); if (!dummyGenericInstance && res is ILType) { ((ILType)res).TypeReference = (TypeReference)token; } if (!string.IsNullOrEmpty(res.FullName)) { if (res is CLRType || !((ILType)res).TypeReference.HasGenericParameters) mapType[res.FullName] = res; } } mapTypeToken[res.GetHashCode()] = res; if (!dummyGenericInstance) mapTypeToken[hash] = res; return res; } public IType GetType(int hash) { IType res; if (mapTypeToken.TryGetValue(hash, out res)) return res; else return null; } /// /// 根据CLR类型获取 IL类型 /// /// /// public IType GetType(Type t) { IType res; if (clrTypeMapping.TryGetValue(t, out res)) return res; else return GetType(t.AssemblyQualifiedName); } /// /// Create a instance of the specified type, which is inherited from a CLR Type /// /// CLR Type /// Full Name of the type /// Arguments for the constructor /// public T Instantiate(string type, object[] args = null) { ILTypeInstance ins = Instantiate(type, args); return (T)ins.CLRInstance; } /// /// Create a instance of the specified type /// /// Full Name of the type /// Arguments for the constructor /// public ILTypeInstance Instantiate(string type, object[] args = null) { IType t; if (mapType.TryGetValue(type, out t)) { ILType ilType = t as ILType; if(ilType != null) { bool hasConstructor = args != null && args.Length != 0; var res = ilType.Instantiate(!hasConstructor); if (hasConstructor) { var ilm = ilType.GetConstructor(args.Length); Invoke(ilm, res, args); } return res; } } return null; } /// /// Invoke a method /// /// Type's fullname /// Method name /// Parameters /// public object Invoke(string type, string method, object instance, params object[] p) { IType t = GetType(type); if (t == null) return null; var m = t.GetMethod(method, p != null ? p.Length : 0); if (m != null) { for(int i = 0; i < m.ParameterCount; i++) { if (p[i] == null) continue; if (!m.Parameters[i].TypeForCLR.IsAssignableFrom(p[i].GetType())) { throw new ArgumentException("Parameter type mismatch"); } } return Invoke(m, instance, p); } return null; } /// /// Invoke a generic method /// /// Type's fullname /// Method name /// Generic Arguments /// Object Instance of the method /// Parameters /// public object InvokeGenericMethod(string type, string method, IType[] genericArguments, object instance, params object[] p) { IType t = GetType(type); if (t == null) return null; var m = t.GetMethod(method, p.Length); if (m != null) { m = m.MakeGenericMethod(genericArguments); return Invoke(m, instance, p); } return null; } /// /// Invokes a specific method /// /// Method /// object instance /// Parameters /// public object Invoke(IMethod m, object instance, params object[] p) { object res = null; if (m is ILMethod) { ILIntepreter inteptreter = null; lock (freeIntepreters) { if (freeIntepreters.Count > 0) { inteptreter = freeIntepreters.Dequeue(); //Clear debug state, because it may be in ShouldBreak State inteptreter.ClearDebugState(); } else { inteptreter = new ILIntepreter(this); #if DEBUG intepreters[inteptreter.GetHashCode()] = inteptreter; debugService.ThreadStarted(inteptreter); #endif } } try { res = inteptreter.Run((ILMethod)m, instance, p); } finally { lock (freeIntepreters) { #if DEBUG if(inteptreter.CurrentStepType!= StepTypes.None) { //We should resume all other threads if we are currently doing stepping operation foreach(var i in intepreters) { if(i.Value != inteptreter) { i.Value.ClearDebugState(); i.Value.Resume(); } } inteptreter.ClearDebugState(); } #endif inteptreter.Stack.ManagedStack.Clear(); inteptreter.Stack.Frames.Clear(); freeIntepreters.Enqueue(inteptreter); #if DEBUG //debugService.ThreadEnded(inteptreter); #endif } } } return res; } internal IMethod GetMethod(object token, ILType contextType,ILMethod contextMethod, out bool invalidToken) { string methodname = null; string typename = null; List paramList = null; int hashCode = token.GetHashCode(); IMethod method; IType[] genericArguments = null; IType returnType; invalidToken = false; bool isConstructor = false; if (mapMethod.TryGetValue(hashCode, out method)) return method; IType type = null; if (token is Mono.Cecil.MethodReference) { Mono.Cecil.MethodReference _ref = (token as Mono.Cecil.MethodReference); if (_ref.FullName == "System.Void System.Object::.ctor()") { mapMethod[hashCode] = null; return null; } if (_ref.FullName == "System.Void System.Attribute::.ctor()") { mapMethod[hashCode] = null; return null; } methodname = _ref.Name; var typeDef = _ref.DeclaringType; type = GetType(typeDef, contextType, contextMethod); if (type == null) throw new KeyNotFoundException("Cannot find type:" + typename); if (token is Mono.Cecil.MethodDefinition) { var def = _ref as MethodDefinition; isConstructor = def.IsConstructor; } else isConstructor = methodname == ".ctor"; if (_ref.IsGenericInstance) { GenericInstanceMethod gim = (GenericInstanceMethod)_ref; genericArguments = new IType[gim.GenericArguments.Count]; for (int i = 0; i < genericArguments.Length; i++) { if (gim.GenericArguments[i].IsGenericParameter) invalidToken = true; var gt = GetType(gim.GenericArguments[i], contextType, contextMethod); if (gt == null) { gt = contextMethod.FindGenericArgument(gim.GenericArguments[i].Name); if (gt == null)//This means it contains unresolved generic arguments, which means it's not searching the generic instance { genericArguments = null; break; } else genericArguments[i] = gt; } else genericArguments[i] = gt; } } if (!invalidToken && typeDef.IsGenericInstance) { GenericInstanceType gim = (GenericInstanceType)typeDef; for (int i = 0; i < gim.GenericArguments.Count; i++) { if (gim.GenericArguments[0].IsGenericParameter) { invalidToken = true; break; } } } paramList = _ref.GetParamList(this, contextType, contextMethod, genericArguments); returnType = GetType(_ref.ReturnType, type, null); if (returnType == null) returnType = GetType(_ref.ReturnType, contextType, null); } else { throw new NotImplementedException(); //Mono.Cecil.GenericInstanceMethod gmethod = _def as Mono.Cecil.GenericInstanceMethod; //genlist = new MethodParamList(environment, gmethod); } if (isConstructor) method = type.GetConstructor(paramList); else { method = type.GetMethod(methodname, paramList, genericArguments, returnType, true); } if (method == null) { if (isConstructor && contextType.FirstCLRBaseType != null && contextType.FirstCLRBaseType is CrossBindingAdaptor && type.TypeForCLR == ((CrossBindingAdaptor)contextType.FirstCLRBaseType).BaseCLRType) { method = contextType.BaseType.GetConstructor(paramList); if (method == null) throw new KeyNotFoundException(string.Format("Cannot find method:{0} in type:{1}, token={2}", methodname, type.FullName, token)); invalidToken = true; mapMethod[method.GetHashCode()] = method; } else throw new KeyNotFoundException(string.Format("Cannot find method:{0} in type:{1}, token={2}", methodname, type.FullName, token)); } if (!invalidToken) mapMethod[hashCode] = method; else mapMethod[method.GetHashCode()] = method; return method; } internal IMethod GetMethod(int tokenHash) { IMethod res; if (mapMethod.TryGetValue(tokenHash, out res)) return res; return null; } internal long GetStaticFieldIndex(object token, IType contextType, IMethod contextMethod) { FieldReference f = token as FieldReference; var type = GetType(f.DeclaringType, contextType, contextMethod); if (type is ILType) { var it = type as ILType; int idx = it.GetFieldIndex(token); long res = 0; if (it.TypeReference.HasGenericParameters) { mapTypeToken[type.GetHashCode()] = it; res = ((long)type.GetHashCode() << 32) | (uint)idx; } else { res = ((long)it.TypeReference.GetHashCode() << 32) | (uint)idx; } return res; } else { int idx = type.GetFieldIndex(token); long res = ((long)type.GetHashCode() << 32) | (uint)idx; return res; } } internal long CacheString(object token) { long oriHash = token.GetHashCode(); long hashCode = oriHash; string str = (string)token; lock (mapString) { bool isCollision = CheckStringCollision(hashCode, str); long cnt = 0; while (isCollision) { cnt++; hashCode = cnt << 32 | oriHash; isCollision = CheckStringCollision(hashCode, str); } mapString[hashCode] = (string)token; } return hashCode; } bool CheckStringCollision(long hashCode, string newStr) { string oldVal; if (mapString.TryGetValue(hashCode, out oldVal)) return oldVal != newStr; return false; } internal string GetString(long hashCode) { string res = null; if (mapString.TryGetValue(hashCode, out res)) return res; return res; } public void RegisterCrossBindingAdaptor(CrossBindingAdaptor adaptor) { var bType = adaptor.BaseCLRType; if (bType != null) { if (!crossAdaptors.ContainsKey(bType)) { var t = adaptor.AdaptorType; var res = GetType(t); if (res == null) { res = new CLRType(t, this); mapType[res.FullName] = res; mapType[t.AssemblyQualifiedName] = res; clrTypeMapping[t] = res; } adaptor.RuntimeType = res; crossAdaptors[bType] = adaptor; } else throw new Exception("Crossbinding Adapter for " + bType.FullName + " is already added."); } else { var bTypes = adaptor.BaseCLRTypes; var t = adaptor.AdaptorType; var res = GetType(t); if (res == null) { res = new CLRType(t, this); mapType[res.FullName] = res; mapType[t.AssemblyQualifiedName] = res; clrTypeMapping[t] = res; } adaptor.RuntimeType = res; foreach (var i in bTypes) { if (!crossAdaptors.ContainsKey(i)) { crossAdaptors[i] = adaptor; } else throw new Exception("Crossbinding Adapter for " + i.FullName + " is already added."); } } } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Enviorment/CLRRedirections.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.CLR.Utils; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Stack; using ILRuntime.Reflection; namespace ILRuntime.Runtime.Enviorment { unsafe static class CLRRedirections { public static StackObject* CreateInstance(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { IType[] genericArguments = method.GenericArguments; if (genericArguments != null && genericArguments.Length == 1) { var t = genericArguments[0]; if (t is ILType) { return ILIntepreter.PushObject(esp, mStack, ((ILType)t).Instantiate()); } else return ILIntepreter.PushObject(esp, mStack, ((CLRType)t).CreateDefaultInstance()); } else throw new EntryPointNotFoundException(); } /*public static object CreateInstance(ILContext ctx, object instance, object[] param, IType[] genericArguments) { if (genericArguments != null && genericArguments.Length == 1) { var t = genericArguments[0]; if (t is ILType) { return ((ILType)t).Instantiate(); } else return Activator.CreateInstance(t.TypeForCLR); } else throw new EntryPointNotFoundException(); }*/ public static StackObject* CreateInstance2(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { var p = esp - 1; var t = mStack[p->Value] as Type; intp.Free(p); if (t != null) { if (t is ILRuntimeType) { return ILIntepreter.PushObject(p, mStack, ((ILRuntimeType)t).ILType.Instantiate()); } else return ILIntepreter.PushObject(p, mStack, Activator.CreateInstance(t)); } else return ILIntepreter.PushNull(p); } /*public static object CreateInstance2(ILContext ctx, object instance, object[] param, IType[] genericArguments) { var t = param[0] as Type; if (t != null) { if (t is ILRuntimeType) { return ((ILRuntimeType)t).ILType.Instantiate(); } else return Activator.CreateInstance(t); } else return null; }*/ public static StackObject* GetType(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { var p = esp - 1; AppDomain dommain = intp.AppDomain; string fullname = (string)StackObject.ToObject(p, dommain, mStack); ; intp.Free(p); var t = intp.AppDomain.GetType(fullname); if (t != null) return ILIntepreter.PushObject(p, mStack, t.ReflectionType); else return ILIntepreter.PushNull(p); } public static StackObject* TypeEquals(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { var ret = ILIntepreter.Minus(esp, 2); var p = esp - 1; AppDomain dommain = intp.AppDomain; var other = StackObject.ToObject(p, dommain, mStack); intp.Free(p); p = ILIntepreter.Minus(esp, 2); var instance = StackObject.ToObject(p, dommain, mStack); intp.Free(p); if(instance is ILRuntimeType) { if (other is ILRuntimeType) { if(((ILRuntimeType)instance).ILType == ((ILRuntimeType)other).ILType) return ILIntepreter.PushOne(ret); else return ILIntepreter.PushZero(ret); } else return ILIntepreter.PushZero(ret); } else { if(((Type)typeof(Type).CheckCLRTypes(instance)).Equals(((Type)typeof(Type).CheckCLRTypes(other)))) return ILIntepreter.PushOne(ret); else return ILIntepreter.PushZero(ret); } } /*public static object GetType(ILContext ctx, object instance, object[] param, IType[] genericArguments) { var t = ctx.AppDomain.GetType((string)param[0]); if (t != null) return t.ReflectionType; else return null; }*/ public unsafe static StackObject* InitializeArray(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var param = esp - 1; byte[] data = StackObject.ToObject(param, domain, mStack) as byte[]; intp.Free(param); param = esp - 1 - 1; object array = StackObject.ToObject(param, domain, mStack); intp.Free(param); if (data == null) return ret; fixed (byte* p = data) { if (array is int[]) { int[] arr = array as int[]; int* ptr = (int*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is byte[]) { byte[] arr = array as byte[]; for (int i = 0; i < arr.Length; i++) { arr[i] = p[i]; } } else if (array is sbyte[]) { sbyte[] arr = array as sbyte[]; sbyte* ptr = (sbyte*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is short[]) { short[] arr = array as short[]; short* ptr = (short*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is ushort[]) { ushort[] arr = array as ushort[]; ushort* ptr = (ushort*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is char[]) { char[] arr = array as char[]; char* ptr = (char*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is uint[]) { uint[] arr = array as uint[]; uint* ptr = (uint*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is Int64[]) { long[] arr = array as long[]; long* ptr = (long*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is UInt64[]) { ulong[] arr = array as ulong[]; ulong* ptr = (ulong*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is float[]) { float[] arr = array as float[]; float* ptr = (float*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is double[]) { double[] arr = array as double[]; double* ptr = (double*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is bool[]) { bool[] arr = array as bool[]; bool* ptr = (bool*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else { throw new NotImplementedException("array=" + array.GetType()); } } return ret; } /*public unsafe static object InitializeArray(ILContext ctx, object instance, object[] param, IType[] genericArguments) { object array = param[0]; byte[] data = param[1] as byte[]; if (data == null) return null; fixed (byte* p = data) { if (array is int[]) { int[] arr = array as int[]; int* ptr = (int*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is byte[]) { byte[] arr = array as byte[]; for (int i = 0; i < arr.Length; i++) { arr[i] = p[i]; } } else if (array is sbyte[]) { sbyte[] arr = array as sbyte[]; sbyte* ptr = (sbyte*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is short[]) { short[] arr = array as short[]; short* ptr = (short*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is ushort[]) { ushort[] arr = array as ushort[]; ushort* ptr = (ushort*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is char[]) { char[] arr = array as char[]; char* ptr = (char*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is uint[]) { uint[] arr = array as uint[]; uint* ptr = (uint*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is Int64[]) { long[] arr = array as long[]; long* ptr = (long*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is UInt64[]) { ulong[] arr = array as ulong[]; ulong* ptr = (ulong*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is float[]) { float[] arr = array as float[]; float* ptr = (float*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is double[]) { double[] arr = array as double[]; double* ptr = (double*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is bool[]) { bool[] arr = array as bool[]; bool* ptr = (bool*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else { throw new NotImplementedException("array=" + array.GetType()); } } return null; }*/ public unsafe static StackObject* DelegateCombine(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { //Don't ask me why not esp -2, unity won't return the right result var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var param = esp - 1; object dele2 = StackObject.ToObject(param, domain, mStack); intp.Free(param); param = esp - 1 - 1; object dele1 = StackObject.ToObject(param, domain, mStack); intp.Free(param); if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) { var dele = ((IDelegateAdapter)dele1); //This means it's the original delegate which should be untouch if (!dele.IsClone) { dele = dele.Clone(); } if(!((IDelegateAdapter)dele2).IsClone) { dele2 = ((IDelegateAdapter)dele2).Clone(); } dele.Combine((IDelegateAdapter)dele2); return ILIntepreter.PushObject(ret, mStack, dele); } else { if (!((IDelegateAdapter)dele1).IsClone) { dele1 = ((IDelegateAdapter)dele1).Clone(); } ((IDelegateAdapter)dele1).Combine((Delegate)dele2); return ILIntepreter.PushObject(ret, mStack, dele1); } } else { if (dele2 is IDelegateAdapter) return ILIntepreter.PushObject(ret, mStack, Delegate.Combine((Delegate)dele1, ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType()))); else return ILIntepreter.PushObject(ret, mStack, Delegate.Combine((Delegate)dele1, (Delegate)dele2)); } } else return ILIntepreter.PushObject(ret, mStack, dele1); } else return ILIntepreter.PushObject(ret, mStack, dele2); } /*public unsafe static object DelegateCombine(ILContext ctx, object instance, object[] param, IType[] genericArguments) { var esp = ctx.ESP; var mStack = ctx.ManagedStack; var domain = ctx.AppDomain; //Don't ask me why not esp -2, unity won't return the right result var dele1 = StackObject.ToObject((esp - 1 - 1), domain, mStack); var dele2 = StackObject.ToObject((esp - 1), domain, mStack); if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) { var dele = ((IDelegateAdapter)dele1); //This means it's the default delegate which should be singleton to support == operator if (dele.Next == null) { dele = dele.Instantiate(domain, dele.Instance, dele.Method); } dele.Combine((IDelegateAdapter)dele2); return dele; } else { ((IDelegateAdapter)dele1).Combine((Delegate)dele2); return dele1; } } else { if (dele2 is IDelegateAdapter) return Delegate.Combine((Delegate)dele1, ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType())); else return Delegate.Combine((Delegate)dele1, (Delegate)dele2); } } else return dele1; } else return dele2; }*/ public unsafe static StackObject* DelegateRemove(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { //Don't ask me why not esp -2, unity won't return the right result var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var param = esp - 1; object dele2 = StackObject.ToObject(param, domain, mStack); intp.Free(param); param = esp - 1 - 1; object dele1 = StackObject.ToObject(param, domain, mStack); intp.Free(param); if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) { if (((IDelegateAdapter)dele1).Equals((IDelegateAdapter)dele2)) return ILIntepreter.PushObject(ret, mStack, ((IDelegateAdapter)dele1).Next); else ((IDelegateAdapter)dele1).Remove((IDelegateAdapter)dele2); } else ((IDelegateAdapter)dele1).Remove((Delegate)dele2); return ILIntepreter.PushObject(ret, mStack, dele1); } else { if (dele2 is IDelegateAdapter) return ILIntepreter.PushObject(ret, mStack, Delegate.Remove((Delegate)dele1, ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType()))); else return ILIntepreter.PushObject(ret, mStack, Delegate.Remove((Delegate)dele1, (Delegate)dele2)); } } else return ILIntepreter.PushObject(ret, mStack, dele1); } else return ILIntepreter.PushNull(ret); } /*public unsafe static object DelegateRemove(ILContext ctx, object instance, object[] param, IType[] genericArguments) { var esp = ctx.ESP; var mStack = ctx.ManagedStack; var domain = ctx.AppDomain; var dele1 = StackObject.ToObject((esp - 1 - 1), domain, mStack); var dele2 = StackObject.ToObject((esp - 1), domain, mStack); if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) { if (dele1 == dele2) return ((IDelegateAdapter)dele1).Next; else ((IDelegateAdapter)dele1).Remove((IDelegateAdapter)dele2); } else ((IDelegateAdapter)dele1).Remove((Delegate)dele2); return dele1; } else { if (dele2 is IDelegateAdapter) return Delegate.Remove((Delegate)dele1, ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType())); else return Delegate.Remove((Delegate)dele1, (Delegate)dele2); } } else return dele1; } else return null; }*/ public unsafe static StackObject* DelegateEqulity(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { //Don't ask me why not esp -2, unity won't return the right result var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var param = esp - 1; object dele2 = StackObject.ToObject(param, domain, mStack); intp.Free(param); param = esp - 1 - 1; object dele1 = StackObject.ToObject(param, domain, mStack); intp.Free(param); bool res = false; if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) res = ((IDelegateAdapter)dele1).Equals((IDelegateAdapter)dele2); else res = ((IDelegateAdapter)dele1).Equals((Delegate)dele2); } else { if (dele2 is IDelegateAdapter) { res = (Delegate)dele1 == ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType()); } else res = (Delegate)dele1 == (Delegate)dele2; } } else res = dele1 == null; } else res = dele2 == null; if (res) return ILIntepreter.PushOne(ret); else return ILIntepreter.PushZero(ret); } /*public unsafe static object DelegateEqulity(ILContext ctx, object instance, object[] param, IType[] genericArguments) { //op_Equality,op_Inequality var esp = ctx.ESP; var mStack = ctx.ManagedStack; var domain = ctx.AppDomain; var dele1 = StackObject.ToObject((esp - 1 - 1), domain, mStack); var dele2 = StackObject.ToObject((esp - 1), domain, mStack); if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) return ((IDelegateAdapter)dele1).Equals((IDelegateAdapter)dele2); else return ((IDelegateAdapter)dele1).Equals((Delegate)dele2); } else { if (dele2 is IDelegateAdapter) { return (Delegate)dele1 == ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType()); } else return (Delegate)dele1 == (Delegate)dele2; } } else return dele1 == null; } else return dele2 == null; }*/ public unsafe static StackObject* DelegateInequlity(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { //Don't ask me why not esp -2, unity won't return the right result var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var param = esp - 1; object dele2 = StackObject.ToObject(param, domain, mStack); intp.Free(param); param = esp - 1 - 1; object dele1 = StackObject.ToObject(param, domain, mStack); intp.Free(param); bool res = false; if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) res = !((IDelegateAdapter)dele1).Equals((IDelegateAdapter)dele2); else res = !((IDelegateAdapter)dele1).Equals((Delegate)dele2); } else { if (dele2 is IDelegateAdapter) res = (Delegate)dele1 != ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType()); else res = (Delegate)dele1 != (Delegate)dele2; } } else res = dele1 != null; } else res = dele2 != null; if (res) return ILIntepreter.PushOne(ret); else return ILIntepreter.PushZero(ret); } /*public unsafe static object DelegateInequlity(ILContext ctx, object instance, object[] param, IType[] genericArguments) { //op_Equality,op_Inequality var esp = ctx.ESP; var mStack = ctx.ManagedStack; var domain = ctx.AppDomain; var dele1 = StackObject.ToObject((esp - 1 - 1), domain, mStack); var dele2 = StackObject.ToObject((esp - 1), domain, mStack); if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) return !((IDelegateAdapter)dele1).Equals((IDelegateAdapter)dele2); else return !((IDelegateAdapter)dele1).Equals((Delegate)dele2); } else { if (dele2 is IDelegateAdapter) return (Delegate)dele1 != ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType()); else return (Delegate)dele1 != (Delegate)dele2; } } else return dele1 != null; } else return dele2 != null; }*/ public static StackObject* GetTypeFromHandle(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { //Nothing to do return esp; } /*public static object GetTypeFromHandle(ILContext ctx, object instance, object[] param, IType[] genericArguments) { return param[0]; }*/ public unsafe static StackObject* MethodInfoInvoke(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { AppDomain domain = intp.AppDomain; //Don't ask me why not esp - 3, unity won't return the right result var ret = ILIntepreter.Minus(esp, 3); var param = esp - 1; var p = StackObject.ToObject(param, domain, mStack); intp.Free(param); param = esp - 1 - 1; var obj = StackObject.ToObject(param, domain, mStack); intp.Free(param); param = ILIntepreter.Minus(esp, 3); object instance = StackObject.ToObject(param, domain, mStack); intp.Free(param); if (instance is ILRuntimeMethodInfo) { if (obj != null) esp = ILIntepreter.PushObject(ret, mStack, obj); else esp = ret; if (p != null) { object[] arr = (object[])p; foreach (var i in arr) { esp = ILIntepreter.PushObject(esp, mStack, i); } } bool unhandled; var ilmethod = ((ILRuntimeMethodInfo)instance).ILMethod; return intp.Execute(ilmethod, esp, out unhandled); } else return ILIntepreter.PushObject(ret, mStack, ((MethodInfo)instance).Invoke(obj, (object[])p)); } /*public unsafe static object MethodInfoInvoke(ILContext ctx, object instance, object[] param, IType[] genericArguments) { var esp = ctx.ESP; var mStack = ctx.ManagedStack; var domain = ctx.AppDomain; var intp = ctx.Interpreter; //Don't ask me why not esp - 3, unity won't return the right result var obj = param[0]; var p = param[1]; if (instance is ILRuntimeMethodInfo) { if (obj != null) esp = ILIntepreter.PushObject(esp, mStack, obj); if (p != null) { object[] arr = (object[])p; foreach (var i in arr) { esp = ILIntepreter.PushObject(esp, mStack, i); } } bool unhandled; var ilmethod = ((ILRuntimeMethodInfo)instance).ILMethod; esp = intp.Execute(ilmethod, esp, out unhandled); object res = null; if (ilmethod.ReturnType != domain.VoidType) { res = StackObject.ToObject((esp - 1),domain, mStack); intp.Free(esp - 1); } return res; } else return ((MethodInfo)instance).Invoke(obj, (object[])p); }*/ public unsafe static StackObject* ObjectGetType(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { AppDomain domain = intp.AppDomain; var ret = esp - 1; var param = esp - 1; var instance = StackObject.ToObject(param, domain, mStack); intp.Free(param); var type = instance.GetType(); if (type == typeof(ILTypeInstance)) { return ILIntepreter.PushObject(ret, mStack, ((ILTypeInstance)instance).Type.ReflectionType); } else return ILIntepreter.PushObject(ret, mStack, type); } /*public unsafe static object ObjectGetType(ILContext ctx, object instance, object[] param, IType[] genericArguments) { var type = instance.GetType(); if (type == typeof(ILTypeInstance)) { return ((ILTypeInstance)instance).Type.ReflectionType; } else return type; }*/ } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Enviorment/CrossBindingAdaptor.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.Method; using ILRuntime.CLR.TypeSystem; using ILRuntime.Runtime.Intepreter; namespace ILRuntime.Runtime.Enviorment { public interface CrossBindingAdaptorType { ILTypeInstance ILInstance { get; } } /// /// This interface is used for inheritance and implementation of CLR Types or interfaces /// public abstract class CrossBindingAdaptor : IType { IType type; /// /// This returns the CLR type to be inherited or CLR interface to be implemented /// public abstract Type BaseCLRType { get; } /// /// If this Adaptor is capable to impelement multuple interfaces, use this Property, AND BaseCLRType should return null /// public virtual Type[] BaseCLRTypes { get { return null; } } public abstract Type AdaptorType { get; } public abstract object CreateCLRInstance(Enviorment.AppDomain appdomain, ILTypeInstance instance); internal IType RuntimeType { get { return type; } set { type = value; } } #region IType Members public IMethod GetMethod(string name, int paramCount, bool declaredOnly = false) { return type.GetMethod(name, paramCount, declaredOnly); } public IMethod GetMethod(string name, List param, IType[] genericArguments, IType returnType = null, bool declaredOnly = false) { return type.GetMethod(name, param, genericArguments, returnType, declaredOnly); } public List GetMethods() { return type.GetMethods(); } public int GetFieldIndex(object token) { return type.GetFieldIndex(token); } public IMethod GetConstructor(List param) { return type.GetConstructor(param); } public bool CanAssignTo(IType type) { bool res = false; if (BaseType != null) res = BaseType.CanAssignTo(type); var interfaces = Implements; if (!res && interfaces != null) { for (int i = 0; i < interfaces.Length; i++) { var im = interfaces[i]; res = im.CanAssignTo(type); if (res) return true; } } return res; } public IType MakeGenericInstance(KeyValuePair[] genericArguments) { return type.MakeGenericInstance(genericArguments); } public IType MakeByRefType() { return type.MakeByRefType(); } public IType MakeArrayType() { return type.MakeArrayType(); } public IType FindGenericArgument(string key) { return type.FindGenericArgument(key); } public IType ResolveGenericType(IType contextType) { return type.ResolveGenericType(contextType); } public IMethod GetVirtualMethod(IMethod method) { return type.GetVirtualMethod(method); } public bool IsGenericInstance { get { return type.IsGenericInstance; } } public KeyValuePair[] GenericArguments { get { return type.GenericArguments; } } public Type TypeForCLR { get { return type.TypeForCLR; } } public IType ByRefType { get { return type.ByRefType; } } public IType ArrayType { get { return type.ArrayType; } } public string FullName { get { return type.FullName; } } public string Name { get { return type.Name; } } public bool IsValueType { get { return type.IsValueType; } } public bool IsPrimitive { get { return type.IsPrimitive; } } public bool IsDelegate { get { return type.IsDelegate; } } public AppDomain AppDomain { get { return type.AppDomain; } } public Type ReflectionType { get { return type.ReflectionType; } } public IType BaseType { get { return type.BaseType; } } public IType[] Implements { get { return type.Implements; } } public bool HasGenericParameter { get { return type.HasGenericParameter; } } public bool IsArray { get { return false; } } #endregion } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Enviorment/DelegateManager.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.Other; using ILRuntime.Runtime.Intepreter; namespace ILRuntime.Runtime.Enviorment { public class DelegateManager { List methods = new List(); List functions = new List(); IDelegateAdapter zeroParamMethodAdapter = new MethodDelegateAdapter(); IDelegateAdapter dummyAdapter = new DummyDelegateAdapter(); Dictionary> clrDelegates = new Dictionary>(new ByReferenceKeyComparer()); Func defaultConverter; Enviorment.AppDomain appdomain; public DelegateManager(Enviorment.AppDomain appdomain) { this.appdomain = appdomain; defaultConverter = DefaultConverterStub; } static Delegate DefaultConverterStub(Delegate dele) { return dele; } public void RegisterDelegateConvertor(Func action) { var type = typeof(T); if (type.IsSubclassOf(typeof(Delegate))) { clrDelegates[type] = action; } else throw new NotSupportedException(); } public void RegisterMethodDelegate() { DelegateMapNode node = new Enviorment.DelegateManager.DelegateMapNode(); node.Adapter = new MethodDelegateAdapter(); node.ParameterTypes = new Type[] { typeof(T1) }; methods.Add(node); RegisterDelegateConvertor>(defaultConverter); } public void RegisterMethodDelegate() { DelegateMapNode node = new Enviorment.DelegateManager.DelegateMapNode(); node.Adapter = new MethodDelegateAdapter(); node.ParameterTypes = new Type[] { typeof(T1), typeof(T2) }; methods.Add(node); RegisterDelegateConvertor>(defaultConverter); } public void RegisterMethodDelegate() { DelegateMapNode node = new Enviorment.DelegateManager.DelegateMapNode(); node.Adapter = new MethodDelegateAdapter(); node.ParameterTypes = new Type[] { typeof(T1), typeof(T2), typeof(T3) }; methods.Add(node); RegisterDelegateConvertor>(defaultConverter); } public void RegisterMethodDelegate() { DelegateMapNode node = new Enviorment.DelegateManager.DelegateMapNode(); node.Adapter = new MethodDelegateAdapter(); node.ParameterTypes = new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) }; methods.Add(node); RegisterDelegateConvertor>(defaultConverter); } public void RegisterFunctionDelegate() { DelegateMapNode node = new Enviorment.DelegateManager.DelegateMapNode(); node.Adapter = new FunctionDelegateAdapter(); node.ParameterTypes = new Type[] { typeof(TResult) }; functions.Add(node); RegisterDelegateConvertor>(defaultConverter); } public void RegisterFunctionDelegate() { DelegateMapNode node = new Enviorment.DelegateManager.DelegateMapNode(); node.Adapter = new FunctionDelegateAdapter(); node.ParameterTypes = new Type[] { typeof(T1), typeof(TResult) }; functions.Add(node); RegisterDelegateConvertor>(defaultConverter); } public void RegisterFunctionDelegate() { DelegateMapNode node = new Enviorment.DelegateManager.DelegateMapNode(); node.Adapter = new FunctionDelegateAdapter(); node.ParameterTypes = new Type[] { typeof(T1), typeof(T2), typeof(TResult) }; functions.Add(node); RegisterDelegateConvertor>(defaultConverter); } public void RegisterFunctionDelegate() { DelegateMapNode node = new Enviorment.DelegateManager.DelegateMapNode(); node.Adapter = new FunctionDelegateAdapter(); node.ParameterTypes = new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(TResult) }; functions.Add(node); RegisterDelegateConvertor>(defaultConverter); } public void RegisterFunctionDelegate() { DelegateMapNode node = new Enviorment.DelegateManager.DelegateMapNode(); node.Adapter = new FunctionDelegateAdapter(); node.ParameterTypes = new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(TResult) }; functions.Add(node); RegisterDelegateConvertor>(defaultConverter); } internal Delegate ConvertToDelegate(Type clrDelegateType, IDelegateAdapter adapter) { Func func; if(adapter is DummyDelegateAdapter) { DelegateAdapter.ThrowAdapterNotFound(adapter.Method); return null; } if (clrDelegates.TryGetValue(clrDelegateType, out func)) { return func(adapter.Delegate); } else { StringBuilder sb = new StringBuilder(); string clsName, rName; bool isByRef; clrDelegateType.GetClassName(out clsName, out rName, out isByRef); sb.AppendLine("Cannot find convertor for " + rName); sb.AppendLine("Please add following code:"); sb.Append("appdomain.DelegateManager.RegisterDelegateConvertor<"); sb.Append(rName); sb.AppendLine(">((act) =>"); sb.AppendLine("{"); sb.Append(" return new "); sb.Append(rName); sb.Append("(("); var mi = clrDelegateType.GetMethod("Invoke"); bool first = true; foreach(var i in mi.GetParameters()) { if (first) { first = false; } else sb.Append(", "); sb.Append(i.Name); } sb.AppendLine(") =>"); sb.AppendLine(" {"); if(mi.ReturnType != appdomain.VoidType.TypeForCLR) { sb.Append(" return ((Func<"); first = true; foreach (var i in mi.GetParameters()) { if (first) { first = false; } else sb.Append(", "); i.ParameterType.GetClassName(out clsName, out rName, out isByRef); sb.Append(rName); } if (!first) sb.Append(", "); mi.ReturnType.GetClassName(out clsName, out rName, out isByRef); sb.Append(rName); } else { sb.Append(" ((Action<"); first = true; foreach (var i in mi.GetParameters()) { if (first) { first = false; } else sb.Append(", "); i.ParameterType.GetClassName(out clsName, out rName, out isByRef); sb.Append(rName); } } sb.Append(">)act)("); first = true; foreach (var i in mi.GetParameters()) { if (first) { first = false; } else sb.Append(", "); sb.Append(i.Name); } sb.AppendLine(");"); sb.AppendLine(" });"); sb.AppendLine("});"); throw new KeyNotFoundException(sb.ToString()); } } internal IDelegateAdapter FindDelegateAdapter(ILTypeInstance instance, ILMethod method) { IDelegateAdapter res; if (method.ReturnType == appdomain.VoidType) { if (method.ParameterCount == 0) { res = zeroParamMethodAdapter.Instantiate(appdomain, instance, method); if (instance != null) instance.SetDelegateAdapter(method, res); return res; } foreach (var i in methods) { if (i.ParameterTypes.Length == method.ParameterCount) { bool match = true; for (int j = 0; j < method.ParameterCount; j++) { if (i.ParameterTypes[j] != method.Parameters[j].TypeForCLR) { match = false; break; } } if (match) { res = i.Adapter.Instantiate(appdomain, instance, method); if (instance != null) instance.SetDelegateAdapter(method, res); return res; } } } } else { foreach (var i in functions) { if (i.ParameterTypes.Length == method.ParameterCount + 1) { bool match = true; for (int j = 0; j < method.ParameterCount; j++) { if (i.ParameterTypes[j] != method.Parameters[j].TypeForCLR) { match = false; break; } } if (match) { if (method.ReturnType.TypeForCLR == i.ParameterTypes[method.ParameterCount]) { res = i.Adapter.Instantiate(appdomain, instance, method); if (instance != null) instance.SetDelegateAdapter(method, res); return res; } } } } } res = dummyAdapter.Instantiate(appdomain, instance, method); if (instance != null) instance.SetDelegateAdapter(method, res); return res; } class DelegateMapNode { public IDelegateAdapter Adapter { get; set; } public Type[] ParameterTypes { get; set; } } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Enviorment/ILContext.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Stack; using ILRuntime.CLR.Method; namespace ILRuntime.Runtime.Enviorment { public unsafe struct ILContext { public AppDomain AppDomain { get; private set; } public StackObject* ESP { get; private set; } public IList ManagedStack { get; private set; } public IMethod Method { get; private set; } public ILIntepreter Interpreter { get; private set; } internal ILContext(AppDomain domain,ILIntepreter intpreter, StackObject* esp, IList mStack, IMethod method) { AppDomain = domain; ESP = esp; ManagedStack = mStack; Method = method; Interpreter = intpreter; } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Enviorment/ValueTypeBinder.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.Method; using ILRuntime.CLR.TypeSystem; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Stack; namespace ILRuntime.Runtime.Enviorment { public unsafe abstract class ValueTypeBinder { CLRType clrType; Enviorment.AppDomain domain; public CLRType CLRType { get { return clrType; } set { if (clrType == null) { clrType = value; domain = value.AppDomain; } else throw new NotSupportedException(); } } public abstract void CopyValueTypeToStack(object ins, StackObject* ptr, IList mStack); public abstract object ToObject(StackObject* esp, IList managedStack); public virtual void RegisterCLRRedirection(Enviorment.AppDomain appdomain) { } protected void CopyValueTypeToStack(ref K ins, StackObject* esp, IList mStack) where K : struct { switch (esp->ObjectType) { case ObjectTypes.ValueTypeObjectReference: { var dst = *(StackObject**)&esp->Value; var vb = ((CLRType)domain.GetType(dst->Value)).ValueTypeBinder as ValueTypeBinder; if (vb != null) { vb.CopyValueTypeToStack(ref ins, dst, mStack); } else throw new NotSupportedException(); } break; case ObjectTypes.Object: mStack[esp->Value] = ins; break; default: throw new NotImplementedException(); } } protected void AssignFromStack(ref K ins, StackObject* esp, IList mStack) where K : struct { switch (esp->ObjectType) { case ObjectTypes.Null: throw new NullReferenceException(); case ObjectTypes.Object: ins = (K)mStack[esp->Value]; break; case ObjectTypes.ValueTypeObjectReference: { var dst = *(StackObject**)&esp->Value; var vb = ((CLRType)domain.GetType(dst->Value)).ValueTypeBinder as ValueTypeBinder; if (vb != null) { vb.AssignFromStack(ref ins, dst, mStack); } else throw new NotSupportedException(); } break; default: throw new NotImplementedException(); } } } public unsafe abstract class ValueTypeBinder : ValueTypeBinder where T : struct { public override unsafe void CopyValueTypeToStack(object ins, StackObject* ptr, IList mStack) { T obj = (T)ins; CopyValueTypeToStack(ref obj, ptr, mStack); } public abstract void CopyValueTypeToStack(ref T ins, StackObject* ptr, IList mStack); public override unsafe object ToObject(StackObject* esp, IList managedStack) { T obj = new T(); AssignFromStack(ref obj, esp, managedStack); return obj; } public abstract void AssignFromStack(ref T ins, StackObject* ptr, IList mStack); } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Extensions.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.Runtime.Stack; namespace ILRuntime.Runtime { static class Extensions { public static void GetClassName(this Type type, out string clsName, out string realClsName, out bool isByRef, bool simpleClassName = false) { isByRef = type.IsByRef; bool isArray = type.IsArray; if (isByRef) type = type.GetElementType(); if (isArray) type = type.GetElementType(); string realNamespace = null; bool isNestedGeneric = false; if (type.IsNested) { string bClsName, bRealClsName; bool tmp; var rt = type.ReflectedType; if(rt.IsGenericType && rt.IsGenericTypeDefinition) { if (type.IsGenericType) { rt = rt.MakeGenericType(type.GetGenericArguments()); isNestedGeneric = true; } } GetClassName(rt, out bClsName, out bRealClsName, out tmp); clsName = simpleClassName ? "" : bClsName + "_"; realNamespace = bRealClsName + "."; } else { clsName = simpleClassName ? "" : (!string.IsNullOrEmpty(type.Namespace) ? type.Namespace.Replace(".", "_") + "_" : ""); realNamespace = !string.IsNullOrEmpty(type.Namespace) ? type.Namespace + "." : null; } clsName = clsName + type.Name.Replace(".", "_").Replace("`", "_").Replace("<", "_").Replace(">", "_"); bool isGeneric = false; string ga = null; if (type.IsGenericType && !isNestedGeneric) { isGeneric = true; clsName += "_"; ga = "<"; var args = type.GetGenericArguments(); bool first = true; foreach (var j in args) { if (first) first = false; else { clsName += "_"; ga += ", "; } string a, b; bool tmp; GetClassName(j, out a, out b, out tmp, true); clsName += a; ga += b; } ga += ">"; } if (!simpleClassName) clsName += "_Binding"; if (isArray) clsName += "_Array"; realClsName = realNamespace; if (isGeneric) { int idx = type.Name.IndexOf("`"); if (idx > 0) { realClsName += type.Name.Substring(0, idx); realClsName += ga; } else realClsName += type.Name; } else realClsName += type.Name; if (isArray) realClsName += "[]"; } public static int ToInt32(this object obj) { if (obj is int) return (int)obj; if (obj is float) return (int)(float)obj; if (obj is long) return (int)(long)obj; if (obj is short) return (int)(short)obj; if (obj is double) return (int)(double)obj; if (obj is byte) return (int)(byte)obj; if (obj is Intepreter.ILEnumTypeInstance) return (int)((Intepreter.ILEnumTypeInstance)obj)[0]; if (obj is uint) return (int)(uint)obj; if (obj is ushort) return (int)(ushort)obj; if (obj is sbyte) return (int)(sbyte)obj; throw new InvalidCastException(); } public static long ToInt64(this object obj) { if (obj is long) return (long)obj; if (obj is int) return (long)(int)obj; if (obj is float) return (long)(float)obj; if (obj is short) return (long)(short)obj; if (obj is double) return (long)(double)obj; if (obj is byte) return (long)(byte)obj; if (obj is uint) return (long)(uint)obj; if (obj is ushort) return (long)(ushort)obj; if (obj is sbyte) return (long)(sbyte)obj; throw new InvalidCastException(); } public static short ToInt16(this object obj) { if (obj is short) return (short)obj; if (obj is long) return (short)(long)obj; if (obj is int) return (short)(int)obj; if (obj is float) return (short)(float)obj; if (obj is double) return (short)(double)obj; if (obj is byte) return (short)(byte)obj; if (obj is uint) return (short)(uint)obj; if (obj is ushort) return (short)(ushort)obj; if (obj is sbyte) return (short)(sbyte)obj; throw new InvalidCastException(); } public static float ToFloat(this object obj) { if (obj is float) return (float)obj; if (obj is int) return (float)(int)obj; if (obj is long) return (float)(long)obj; if (obj is short) return (float)(short)obj; if (obj is double) return (float)(double)obj; if (obj is byte) return (float)(byte)obj; if (obj is uint) return (float)(uint)obj; if (obj is ushort) return (float)(ushort)obj; if (obj is sbyte) return (float)(sbyte)obj; throw new InvalidCastException(); } public static double ToDouble(this object obj) { if (obj is double) return (double)obj; if (obj is float) return (float)obj; if (obj is int) return (double)(int)obj; if (obj is long) return (double)(long)obj; if (obj is short) return (double)(short)obj; if (obj is byte) return (double)(byte)obj; if (obj is uint) return (double)(uint)obj; if (obj is ushort) return (double)(ushort)obj; if (obj is sbyte) return (double)(sbyte)obj; throw new InvalidCastException(); } public static Type GetActualType(this object value) { if (value is ILRuntime.Runtime.Enviorment.CrossBindingAdaptorType) return ((ILRuntime.Runtime.Enviorment.CrossBindingAdaptorType)value).ILInstance.Type.ReflectionType; if (value is ILRuntime.Runtime.Intepreter.ILTypeInstance) return ((ILRuntime.Runtime.Intepreter.ILTypeInstance)value).Type.ReflectionType; else return value.GetType(); } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Intepreter/DelegateAdapter.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.Runtime; using ILRuntime.Runtime.Stack; using ILRuntime.Other; using ILRuntime.Runtime.Enviorment; namespace ILRuntime.Runtime.Intepreter { #region Functions class FunctionDelegateAdapter : DelegateAdapter { Func action; public FunctionDelegateAdapter() { } private FunctionDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } TResult InvokeILMethod() { if (method.HasThis) return (TResult)appdomain.Invoke(method, instance, null); else return (TResult)appdomain.Invoke(method, null, null); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new FunctionDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new FunctionDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Func)dele; } public override void Remove(Delegate dele) { action -= (Func)dele; } } class FunctionDelegateAdapter : DelegateAdapter { Func action; public FunctionDelegateAdapter() { } private FunctionDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } TResult InvokeILMethod(T1 p1) { if (method.HasThis) return (TResult)appdomain.Invoke(method, instance, p1); else return (TResult)appdomain.Invoke(method, null, p1); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new FunctionDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new FunctionDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Func)dele; } public override void Remove(Delegate dele) { action -= (Func)dele; } } class FunctionDelegateAdapter : DelegateAdapter { Func action; public FunctionDelegateAdapter() { } private FunctionDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } TResult InvokeILMethod(T1 p1, T2 p2) { if (method.HasThis) return (TResult)appdomain.Invoke(method, instance, p1, p2); else return (TResult)appdomain.Invoke(method, null, p1, p2); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new FunctionDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new FunctionDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Func)dele; } public override void Remove(Delegate dele) { action -= (Func)dele; } } class FunctionDelegateAdapter : DelegateAdapter { Func action; public FunctionDelegateAdapter() { } private FunctionDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } TResult InvokeILMethod(T1 p1, T2 p2, T3 p3) { if (method.HasThis) return (TResult)appdomain.Invoke(method, instance, p1, p2, p3); else return (TResult)appdomain.Invoke(method, null, p1, p2, p3); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new FunctionDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new FunctionDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Func)dele; } public override void Remove(Delegate dele) { action -= (Func)dele; } } class FunctionDelegateAdapter : DelegateAdapter { Func action; public FunctionDelegateAdapter() { } private FunctionDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } TResult InvokeILMethod(T1 p1, T2 p2, T3 p3, T4 p4) { if (method.HasThis) return (TResult)appdomain.Invoke(method, instance, p1, p2, p3, p4); else return (TResult)appdomain.Invoke(method, null, p1, p2, p3, p4); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new FunctionDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new FunctionDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Func)dele; } public override void Remove(Delegate dele) { action -= (Func)dele; } } #endregion #region Methods class MethodDelegateAdapter : DelegateAdapter { Action action; public MethodDelegateAdapter() { } private MethodDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } void InvokeILMethod(T1 p1) { if (method.HasThis) appdomain.Invoke(method, instance, p1); else appdomain.Invoke(method, null, p1); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new MethodDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new MethodDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Action)dele; } public override void Remove(Delegate dele) { action -= (Action)dele; } } class MethodDelegateAdapter : DelegateAdapter { Action action; public MethodDelegateAdapter() { } private MethodDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } void InvokeILMethod(T1 p1, T2 p2) { if (method.HasThis) appdomain.Invoke(method, instance, p1, p2); else appdomain.Invoke(method, instance, p1, p2); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new MethodDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new MethodDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Action)dele; } public override void Remove(Delegate dele) { action -= (Action)dele; } } class MethodDelegateAdapter : DelegateAdapter { Action action; public MethodDelegateAdapter() { } private MethodDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } void InvokeILMethod(T1 p1, T2 p2, T3 p3) { if (method.HasThis) appdomain.Invoke(method, instance, p1, p2, p3); else appdomain.Invoke(method, null, p1, p2, p3); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new MethodDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new MethodDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Action)dele; } public override void Remove(Delegate dele) { action -= (Action)dele; } } class MethodDelegateAdapter : DelegateAdapter { Action action; public MethodDelegateAdapter() { } private MethodDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } void InvokeILMethod(T1 p1, T2 p2, T3 p3, T4 p4) { if (method.HasThis) appdomain.Invoke(method, instance, p1, p2, p3, p4); else appdomain.Invoke(method, null, p1, p2, p3, p4); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new MethodDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new MethodDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Action)dele; } public override void Remove(Delegate dele) { action -= (Action)dele; } } class MethodDelegateAdapter : DelegateAdapter { Action action; public MethodDelegateAdapter() { } protected MethodDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Delegate Delegate { get { return action; } } void InvokeILMethod() { if (method.HasThis) appdomain.Invoke(method, instance, null); else appdomain.Invoke(method, null, null); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new MethodDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new MethodDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Action)dele; } public override void Remove(Delegate dele) { action -= (Action)dele; } } class DummyDelegateAdapter : DelegateAdapter { public DummyDelegateAdapter() { } protected DummyDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { } public override Delegate Delegate { get { ThrowAdapterNotFound(method); return null; } } void InvokeILMethod() { if (method.HasThis) appdomain.Invoke(method, instance, null); else appdomain.Invoke(method, null, null); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new DummyDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new DummyDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { ThrowAdapterNotFound(method); } public override void Remove(Delegate dele) { ThrowAdapterNotFound(method); } } #endregion abstract class DelegateAdapter : ILTypeInstance, IDelegateAdapter { protected ILMethod method; protected ILTypeInstance instance; protected Enviorment.AppDomain appdomain; Dictionary converters; IDelegateAdapter next; protected bool isClone; public abstract Delegate Delegate { get; } public IDelegateAdapter Next { get { return next; } } public ILTypeInstance Instance { get { return instance; } } public ILMethod Method { get { return method; } } protected DelegateAdapter() { } protected DelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { this.appdomain = appdomain; this.instance = instance; this.method = method; CLRInstance = this; } public override bool IsValueType { get { return false; } } public unsafe StackObject* ILInvoke(ILIntepreter intp, StackObject* esp, IList mStack) { var ebp = esp; esp = ILInvokeSub(intp, esp, mStack); return ClearStack(intp, esp, ebp, mStack); } unsafe StackObject* ILInvokeSub(ILIntepreter intp, StackObject* esp, IList mStack) { var ebp = esp; bool unhandled; if (method.HasThis) esp = ILIntepreter.PushObject(esp, mStack, instance); int paramCnt = method.ParameterCount; for(int i = paramCnt; i > 0; i--) { intp.CopyToStack(esp, Minus(ebp, i), mStack); esp++; } var ret = intp.Execute(method, esp, out unhandled); if (next != null) { if (method.ReturnType != appdomain.VoidType) { intp.Free(ret - 1);//Return value for multicast delegate doesn't make sense, only return the last one's value } DelegateAdapter n = (DelegateAdapter)next; ret = n.ILInvokeSub(intp, ebp, mStack); } return ret; } unsafe StackObject* ClearStack(ILIntepreter intp, StackObject* esp, StackObject* ebp, IList mStack) { int paramCnt = method.ParameterCount; object retObj = null; StackObject retSObj = StackObject.Null; bool hasReturn = method.ReturnType != appdomain.VoidType; if (hasReturn) { var ret = esp - 1; retSObj = *ret; if(ret->ObjectType>= ObjectTypes.Object) { retObj = mStack[ret->Value]; } intp.Free(ret); } for (int i = 1; i <= paramCnt; i++) { intp.Free(ebp - i); } var returnVal = Minus(ebp, paramCnt + 1); intp.Free(returnVal);//Free delegateInstance if (hasReturn) { *returnVal = retSObj; if(retObj != null) { returnVal->Value = mStack.Count; mStack.Add(retObj); } returnVal++; } return returnVal; } public abstract IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method); public new abstract IDelegateAdapter Clone(); public bool IsClone { get { return isClone; } } public virtual void Combine(IDelegateAdapter adapter) { if (next != null) next.Combine(adapter); else next = adapter; } public abstract void Combine(Delegate dele); public virtual void Remove(IDelegateAdapter adapter) { if (next != null) { if (next.Equals(adapter)) { next = ((DelegateAdapter)next).next; } else next.Remove(adapter); } } public abstract void Remove(Delegate dele); public virtual bool Equals(IDelegateAdapter adapter) { if (adapter is DelegateAdapter) { DelegateAdapter b = (DelegateAdapter)adapter; return instance == b.instance && method == b.method; } else return false; } public virtual bool Equals(Delegate dele) { return Delegate == dele; } public override string ToString() { return method.ToString(); } public Delegate GetConvertor(Type type) { if (converters == null) converters = new Dictionary(new ByReferenceKeyComparer()); Delegate res; if (converters.TryGetValue(type, out res)) return res; else { res = appdomain.DelegateManager.ConvertToDelegate(type, this); converters[type] = res; return res; } } unsafe StackObject* Minus(StackObject* a, int b) { return (StackObject*)((long)a - sizeof(StackObject) * b); } public static void ThrowAdapterNotFound(IMethod method) { StringBuilder sb = new StringBuilder(); sb.Append("Cannot find Delegate Adapter for:"); sb.Append(method.ToString()); string clsName, rName; bool isByRef; if (method.ReturnType.Name != "Void" || method.ParameterCount > 0) { sb.AppendLine(", Please add following code:"); if (method.ReturnType.Name == "Void") { sb.Append("appdomain.DelegateManager.RegisterMethodDelegate<"); bool first = true; foreach(var i in method.Parameters) { if (first) { first = false; } else { sb.Append(", "); } i.TypeForCLR.GetClassName(out clsName, out rName, out isByRef); sb.Append(rName); } sb.AppendLine(">();"); } else { sb.Append("appdomain.DelegateManager.RegisterFunctionDelegate<"); bool first = true; foreach (var i in method.Parameters) { if (first) { first = false; } else { sb.Append(", "); } i.TypeForCLR.GetClassName(out clsName, out rName, out isByRef); sb.Append(rName); } if (!first) sb.Append(", "); method.ReturnType.TypeForCLR.GetClassName(out clsName, out rName, out isByRef); sb.Append(rName); sb.AppendLine(">();"); } } throw new KeyNotFoundException(sb.ToString()); } } unsafe interface IDelegateAdapter { Delegate Delegate { get; } IDelegateAdapter Next { get; } ILTypeInstance Instance { get; } ILMethod Method { get; } StackObject* ILInvoke(ILIntepreter intp, StackObject* esp, IList mStack); IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method); bool IsClone { get; } IDelegateAdapter Clone(); Delegate GetConvertor(Type type); void Combine(IDelegateAdapter adapter); void Combine(Delegate dele); void Remove(IDelegateAdapter adapter); void Remove(Delegate dele); bool Equals(IDelegateAdapter adapter); bool Equals(Delegate dele); } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Intepreter/ILIntepreter.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Stack; using ILRuntime.CLR.Method; using ILRuntime.CLR.TypeSystem; using ILRuntime.Runtime.Intepreter.OpCodes; using ILRuntime.Runtime.Debugger; using ILRuntime.CLR.Utils; using ILRuntime.Other; namespace ILRuntime.Runtime.Intepreter { public unsafe class ILIntepreter { Enviorment.AppDomain domain; RuntimeStack stack; object _lockObj; bool allowUnboundCLRMethod; public RuntimeStack Stack { get { return stack; } } public bool ShouldBreak { get; set; } public StepTypes CurrentStepType { get; set; } public StackObject* LastStepFrameBase { get; set; } public int LastStepInstructionIndex { get; set; } StackObject* ValueTypeBasePointer; public ILIntepreter(Enviorment.AppDomain domain) { this.domain = domain; stack = new RuntimeStack(this); allowUnboundCLRMethod = domain.AllowUnboundCLRMethod; #if DEBUG _lockObj = new object(); #endif } public Enviorment.AppDomain AppDomain { get { return domain; } } public void Break() { //Clear old debug state ClearDebugState(); lock (_lockObj) Monitor.Wait(_lockObj); } public void Resume() { lock (_lockObj) Monitor.Pulse(_lockObj); } public void ClearDebugState() { ShouldBreak = false; CurrentStepType = StepTypes.None; LastStepFrameBase = (StackObject*)0; LastStepInstructionIndex = 0; } public object Run(ILMethod method, object instance, object[] p) { IList mStack = stack.ManagedStack; int mStackBase = mStack.Count; StackObject* esp = stack.StackBase; stack.ResetValueTypePointer(); if (method.HasThis) { if (instance is CrossBindingAdaptorType) instance = ((CrossBindingAdaptorType)instance).ILInstance; if (instance == null) throw new NullReferenceException("instance should not be null!"); esp = PushObject(esp, mStack, instance); } esp = PushParameters(method, esp, p); bool unhandledException; esp = Execute(method, esp, out unhandledException); object result = method.ReturnType != domain.VoidType ? method.ReturnType.TypeForCLR.CheckCLRTypes(StackObject.ToObject((esp - 1), domain, mStack)) : null; //ClearStack #if DEBUG ((List)mStack).RemoveRange(mStackBase, mStack.Count - mStackBase); #else ((UncheckedList)mStack).RemoveRange(mStackBase, mStack.Count - mStackBase); #endif return result; } internal StackObject* Execute(ILMethod method, StackObject* esp, out bool unhandledException) { if (method == null) throw new NullReferenceException(); #if UNITY_EDITOR if (System.Threading.Thread.CurrentThread.ManagedThreadId == AppDomain.UnityMainThreadID) #if UNITY_5_5_OR_NEWER UnityEngine.Profiling.Profiler.BeginSample(method.ToString()); #else UnityEngine.Profiler.BeginSample(method.ToString()); #endif #endif OpCode[] body = method.Body; StackFrame frame; stack.InitializeFrame(method, esp, out frame); StackObject* v1 = frame.LocalVarPointer; StackObject* v2 = frame.LocalVarPointer + 1; StackObject* v3 = frame.LocalVarPointer + 1 + 1; StackObject* v4 = Add(frame.LocalVarPointer, 3); int finallyEndAddress = 0; esp = frame.BasePointer; StackObject* arg = Minus(frame.LocalVarPointer, method.ParameterCount); IList mStack = stack.ManagedStack; int paramCnt = method.ParameterCount; if (method.HasThis)//this parameter is always object reference { arg--; paramCnt++; } unhandledException = false; //Managed Stack reserved for arguments(In case of starg) for (int i = 0; i < paramCnt; i++) { var a = Add(arg, i); switch (a->ObjectType) { case ObjectTypes.Null: //Need to reserve place for null, in case of starg a->ObjectType = ObjectTypes.Object; a->Value = mStack.Count; mStack.Add(null); break; case ObjectTypes.ValueTypeObjectReference: CloneStackValueType(a, a, mStack); break; case ObjectTypes.Object: case ObjectTypes.FieldReference: case ObjectTypes.ArrayReference: frame.ManagedStackBase--; break; } } stack.PushFrame(ref frame); int locBase = mStack.Count; //Managed Stack reserved for local variable for (int i = 0; i < method.LocalVariableCount; i++) { mStack.Add(null); } for (int i = 0; i < method.LocalVariableCount; i++) { var v = method.Variables[i]; if (v.VariableType.IsValueType && !v.VariableType.IsPrimitive) { var t = AppDomain.GetType(v.VariableType, method.DeclearingType, method); if (t is ILType) { //var obj = ((ILType)t).Instantiate(false); var loc = Add(v1, i); stack.AllocValueType(loc, t); /*loc->ObjectType = ObjectTypes.Object; loc->Value = mStack.Count; mStack.Add(obj);*/ } else { CLRType cT = (CLRType)t; var loc = Add(v1, i); if (cT.ValueTypeBinder != null) { stack.AllocValueType(loc, t); } else { var obj = ((CLRType)t).CreateDefaultInstance(); loc->ObjectType = ObjectTypes.Object; loc->Value = locBase + i; mStack[locBase + i] = obj; } } } else { if (v.VariableType.IsPrimitive) { var t = AppDomain.GetType(v.VariableType, method.DeclearingType, method); var loc = Add(v1, i); StackObject.Initialized(loc, t); } else { var loc = Add(v1, i); loc->ObjectType = ObjectTypes.Object; loc->Value = locBase + i; } } } var bp = stack.ValueTypeStackPointer; ValueTypeBasePointer = bp; fixed (OpCode* ptr = body) { OpCode* ip = ptr; OpCodeEnum code = ip->Code; bool returned = false; while (!returned) { try { #if DEBUG if (ShouldBreak) Break(); var insOffset = (int)(ip - ptr); frame.Address.Value = insOffset; AppDomain.DebugService.CheckShouldBreak(method, this, insOffset); #endif code = ip->Code; switch (code) { #region Arguments and Local Variable case OpCodeEnum.Ldarg_0: CopyToStack(esp, arg, mStack); esp++; break; case OpCodeEnum.Ldarg_1: CopyToStack(esp, arg + 1, mStack); esp++; break; case OpCodeEnum.Ldarg_2: CopyToStack(esp, arg + 1 + 1, mStack); esp++; break; case OpCodeEnum.Ldarg_3: CopyToStack(esp, arg + 1 + 1 + 1, mStack); esp++; break; case OpCodeEnum.Ldarg: case OpCodeEnum.Ldarg_S: CopyToStack(esp, Add(arg, ip->TokenInteger), mStack); esp++; break; case OpCodeEnum.Ldarga: case OpCodeEnum.Ldarga_S: { var a = Add(arg, ip->TokenInteger); esp->ObjectType = ObjectTypes.StackObjectReference; *(StackObject**)&esp->Value = a; esp++; } break; case OpCodeEnum.Starg: case OpCodeEnum.Starg_S: { var a = Add(arg, ip->TokenInteger); var val = esp - 1; int idx = a->Value; bool isObj = a->ObjectType >= ObjectTypes.Object; if (val->ObjectType >= ObjectTypes.Object) { a->ObjectType = val->ObjectType; mStack[a->Value] = mStack[val->Value]; a->ValueLow = val->ValueLow; } else { *a = *val; if (isObj) { a->Value = idx; if (val->ObjectType == ObjectTypes.Null) { mStack[a->Value] = null; } } } Free(val); esp--; } break; case OpCodeEnum.Stloc_0: { esp--; int idx = locBase; StLocSub(esp, v1, bp, idx, mStack); } break; case OpCodeEnum.Ldloc_0: CopyToStack(esp, v1, mStack); esp++; break; case OpCodeEnum.Stloc_1: { esp--; int idx = locBase + 1; StLocSub(esp, v2, bp, idx, mStack); } break; case OpCodeEnum.Ldloc_1: CopyToStack(esp, v2, mStack); esp++; break; case OpCodeEnum.Stloc_2: { esp--; int idx = locBase + 2; StLocSub(esp, v3, bp, idx, mStack); break; } case OpCodeEnum.Ldloc_2: CopyToStack(esp, v3, mStack); esp++; break; case OpCodeEnum.Stloc_3: { esp--; int idx = locBase + 3; StLocSub(esp, v4, bp, idx, mStack); } break; case OpCodeEnum.Ldloc_3: CopyToStack(esp, v4, mStack); esp++; break; case OpCodeEnum.Stloc: case OpCodeEnum.Stloc_S: { esp--; var v = Add(frame.LocalVarPointer, ip->TokenInteger); int idx = locBase + ip->TokenInteger; StLocSub(esp, v, bp, idx, mStack); } break; case OpCodeEnum.Ldloc: case OpCodeEnum.Ldloc_S: { var v = Add(frame.LocalVarPointer, ip->TokenInteger); CopyToStack(esp, v, mStack); esp++; } break; case OpCodeEnum.Ldloca: case OpCodeEnum.Ldloca_S: { var v = Add(frame.LocalVarPointer, ip->TokenInteger); esp->ObjectType = ObjectTypes.StackObjectReference; *(StackObject**)&esp->Value = v; esp++; } break; case OpCodeEnum.Ldobj: { var objRef = esp - 1; switch (objRef->ObjectType) { case ObjectTypes.ArrayReference: { var t = AppDomain.GetType(ip->TokenInteger); var obj = mStack[objRef->Value]; var idx = objRef->ValueLow; Free(objRef); LoadFromArrayReference(obj, idx, objRef, t, mStack); } break; case ObjectTypes.StackObjectReference: { var obj = GetObjectAndResolveReference(objRef); *objRef = *obj; if (objRef->ObjectType >= ObjectTypes.Object) { objRef->Value = mStack.Count; mStack.Add(mStack[obj->Value]); } } break; case ObjectTypes.FieldReference: { var obj = mStack[objRef->Value]; int idx = objRef->ValueLow; Free(objRef); if (obj is ILTypeInstance) { ((ILTypeInstance)obj).PushToStack(idx, objRef, AppDomain, mStack); } else { var t = AppDomain.GetType(ip->TokenInteger); obj = ((CLRType) t).GetFieldValue(idx, obj); PushObject(objRef, mStack, obj); } } break; case ObjectTypes.StaticFieldReference: { var t = AppDomain.GetType(objRef->Value); int idx = objRef->ValueLow; Free(objRef); if (t is ILType) { ((ILType)t).StaticInstance.PushToStack(idx, objRef, AppDomain, mStack); } else { var obj = ((CLRType)t).GetFieldValue(idx, null); PushObject(objRef, mStack, obj); } } break; default: throw new NotImplementedException(); } } break; case OpCodeEnum.Stobj: { var objRef = esp - 1 - 1; var val = esp - 1; switch (objRef->ObjectType) { case ObjectTypes.ArrayReference: { var t = AppDomain.GetType(ip->TokenInteger); StoreValueToArrayReference(objRef, val, t, mStack); } break; case ObjectTypes.StackObjectReference: { objRef = GetObjectAndResolveReference(objRef); if (val->ObjectType >= ObjectTypes.Object) { mStack[objRef->Value] = mStack[val->Value]; objRef->ValueLow = val->ValueLow; } else { *objRef = *val; } } break; case ObjectTypes.FieldReference: { var obj = mStack[objRef->Value]; int idx = objRef->ValueLow; if (obj is ILTypeInstance) { ((ILTypeInstance)obj).AssignFromStack(idx, val, AppDomain, mStack); } else { var t = AppDomain.GetType(ip->TokenInteger); ((CLRType)t).SetFieldValue(idx, ref obj, t.TypeForCLR.CheckCLRTypes(StackObject.ToObject(val, AppDomain, mStack))); } } break; case ObjectTypes.StaticFieldReference: { var t = AppDomain.GetType(objRef->Value); if (t is ILType) { ((ILType)t).StaticInstance.AssignFromStack(objRef->ValueLow, val, AppDomain, mStack); } else { ((CLRType)t).SetStaticFieldValue(objRef->ValueLow, t.TypeForCLR.CheckCLRTypes(StackObject.ToObject(val, AppDomain, mStack))); } } break; default: throw new NotImplementedException(); } Free(esp - 1); Free(esp - 1 - 1); esp = esp - 1 - 1; } break; #endregion #region Load Constants case OpCodeEnum.Ldc_I4_M1: esp->Value = -1; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4_0: esp->Value = 0; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4_1: esp->Value = 1; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4_2: esp->Value = 2; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4_3: esp->Value = 3; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4_4: esp->Value = 4; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4_5: esp->Value = 5; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4_6: esp->Value = 6; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4_7: esp->Value = 7; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4_8: esp->Value = 8; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I4: case OpCodeEnum.Ldc_I4_S: esp->Value = ip->TokenInteger; esp->ObjectType = ObjectTypes.Integer; esp++; break; case OpCodeEnum.Ldc_I8: { *(long*)(&esp->Value) = ip->TokenLong; esp->ObjectType = ObjectTypes.Long; esp++; } break; case OpCodeEnum.Ldc_R4: { *(float*)(&esp->Value) = *(float*)&ip->TokenInteger; esp->ObjectType = ObjectTypes.Float; esp++; } break; case OpCodeEnum.Ldc_R8: { *(double*)(&esp->Value) = *(double*)&ip->TokenLong; esp->ObjectType = ObjectTypes.Double; esp++; } break; case OpCodeEnum.Ldnull: { esp = PushNull(esp); } break; case OpCodeEnum.Ldind_I: case OpCodeEnum.Ldind_I1: case OpCodeEnum.Ldind_I2: case OpCodeEnum.Ldind_I4: case OpCodeEnum.Ldind_U1: case OpCodeEnum.Ldind_U2: case OpCodeEnum.Ldind_U4: { var val = GetObjectAndResolveReference(esp - 1); var dst = esp - 1; switch (val->ObjectType) { case ObjectTypes.FieldReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromFieldReference(instance, idx, dst, mStack); } break; case ObjectTypes.ArrayReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromArrayReference(instance, idx, dst, instance.GetType().GetElementType(), mStack); } break; default: { dst->ObjectType = ObjectTypes.Integer; dst->Value = val->Value; dst->ValueLow = 0; } break; } } break; case OpCodeEnum.Ldind_I8: { var val = GetObjectAndResolveReference(esp - 1); var dst = esp - 1; switch (val->ObjectType) { case ObjectTypes.FieldReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromFieldReference(instance, idx, dst, mStack); } break; case ObjectTypes.ArrayReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromArrayReference(instance, idx, dst, instance.GetType().GetElementType(), mStack); } break; default: { *dst = *val; dst->ObjectType = ObjectTypes.Long; dst->ValueLow = 0; } break; } } break; case OpCodeEnum.Ldind_R4: { var val = GetObjectAndResolveReference(esp - 1); var dst = esp - 1; switch (val->ObjectType) { case ObjectTypes.FieldReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromFieldReference(instance, idx, dst, mStack); } break; case ObjectTypes.ArrayReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromArrayReference(instance, idx, dst, instance.GetType().GetElementType(), mStack); } break; default: { dst->ObjectType = ObjectTypes.Float; dst->Value = val->Value; dst->ValueLow = 0; } break; } } break; case OpCodeEnum.Ldind_R8: { var val = GetObjectAndResolveReference(esp - 1); var dst = esp - 1; switch (val->ObjectType) { case ObjectTypes.FieldReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromFieldReference(instance, idx, dst, mStack); } break; case ObjectTypes.ArrayReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromArrayReference(instance, idx, dst, instance.GetType().GetElementType(), mStack); } break; default: { *dst = *val; dst->ObjectType = ObjectTypes.Double; } break; } } break; case OpCodeEnum.Ldind_Ref: { var val = GetObjectAndResolveReference(esp - 1); var dst = esp - 1; switch (val->ObjectType) { case ObjectTypes.FieldReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromFieldReference(instance, idx, dst, mStack); } break; case ObjectTypes.ArrayReference: { var instance = mStack[val->Value]; var idx = val->ValueLow; Free(dst); LoadFromArrayReference(instance, idx, dst, instance.GetType().GetElementType(), mStack); } break; default: { dst->ObjectType = ObjectTypes.Object; dst->Value = mStack.Count; mStack.Add(mStack[val->Value]); } break; } } break; case OpCodeEnum.Stind_I: case OpCodeEnum.Stind_I1: case OpCodeEnum.Stind_I2: case OpCodeEnum.Stind_I4: case OpCodeEnum.Stind_R4: { var dst = GetObjectAndResolveReference(esp - 1 - 1); var val = esp - 1; switch (dst->ObjectType) { case ObjectTypes.FieldReference: { StoreValueToFieldReference(mStack[dst->Value], dst->ValueLow, val, mStack); } break; case ObjectTypes.ArrayReference: { StoreValueToArrayReference(dst, val, mStack[dst->Value].GetType().GetElementType(), mStack); } break; default: { dst->Value = val->Value; } break; } Free(esp - 1); Free(esp - 1 - 1); esp = esp - 1 - 1; } break; case OpCodeEnum.Stind_I8: case OpCodeEnum.Stind_R8: { var dst = GetObjectAndResolveReference(esp - 1 - 1); var val = esp - 1; switch (dst->ObjectType) { case ObjectTypes.FieldReference: { StoreValueToFieldReference(mStack[dst->Value], dst->ValueLow, val, mStack); } break; default: { dst->Value = val->Value; dst->ValueLow = val->ValueLow; } break; } Free(esp - 1); Free(esp - 1 - 1); esp = esp - 1 - 1; } break; case OpCodeEnum.Stind_Ref: { var dst = GetObjectAndResolveReference(esp - 1 - 1); var val = esp - 1; switch (dst->ObjectType) { case ObjectTypes.FieldReference: { StoreValueToFieldReference(mStack[dst->Value], dst->ValueLow, val, mStack); } break; default: { switch (val->ObjectType) { case ObjectTypes.Object: mStack[dst->Value] = mStack[val->Value]; break; case ObjectTypes.Null: mStack[dst->Value] = null; break; default: throw new NotImplementedException(); } } break; } Free(esp - 1); Free(esp - 1 - 1); esp = esp - 1 - 1; } break; case OpCodeEnum.Ldstr: esp = PushObject(esp, mStack, AppDomain.GetString(ip->TokenLong)); break; #endregion #region Althemetics case OpCodeEnum.Add: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) + *((long*)&b->Value); break; case ObjectTypes.Integer: esp->Value = a->Value + b->Value; break; case ObjectTypes.Float: *((float*)&esp->Value) = *((float*)&a->Value) + *((float*)&b->Value); break; case ObjectTypes.Double: *((double*)&esp->Value) = *((double*)&a->Value) + *((double*)&b->Value); break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Sub: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) - *((long*)&b->Value); break; case ObjectTypes.Integer: esp->Value = a->Value - b->Value; break; case ObjectTypes.Float: *((float*)&esp->Value) = *((float*)&a->Value) - *((float*)&b->Value); break; case ObjectTypes.Double: *((double*)&esp->Value) = *((double*)&a->Value) - *((double*)&b->Value); break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Mul: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) * *((long*)&b->Value); break; case ObjectTypes.Integer: esp->Value = a->Value * b->Value; break; case ObjectTypes.Float: *((float*)&esp->Value) = *((float*)&a->Value) * *((float*)&b->Value); break; case ObjectTypes.Double: *((double*)&esp->Value) = *((double*)&a->Value) * *((double*)&b->Value); break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Div: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) / *((long*)&b->Value); break; case ObjectTypes.Integer: esp->Value = a->Value / b->Value; break; case ObjectTypes.Float: *((float*)&esp->Value) = *((float*)&a->Value) / *((float*)&b->Value); break; case ObjectTypes.Double: *((double*)&esp->Value) = *((double*)&a->Value) / *((double*)&b->Value); break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Div_Un: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((ulong*)&esp->Value) = *((ulong*)&a->Value) / *((ulong*)&b->Value); break; case ObjectTypes.Integer: esp->Value = (int)((uint)a->Value / (uint)b->Value); break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Rem: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) % *((long*)&b->Value); break; case ObjectTypes.Integer: esp->Value = a->Value % b->Value; break; case ObjectTypes.Float: *(float*)&esp->Value = *(float*)&a->Value % *(float*)&b->Value; break; case ObjectTypes.Double: *(double*)&esp->Value = *(double*)&a->Value % *(double*)&b->Value; break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Rem_Un: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((ulong*)&esp->Value) = *((ulong*)&a->Value) % *((ulong*)&b->Value); break; case ObjectTypes.Integer: esp->Value = (int)((uint)a->Value % (uint)b->Value); break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Xor: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) ^ *((long*)&b->Value); break; case ObjectTypes.Integer: esp->Value = a->Value ^ b->Value; break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.And: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) & *((long*)&b->Value); break; case ObjectTypes.Integer: esp->Value = a->Value & b->Value; break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Or: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) | *((long*)&b->Value); break; case ObjectTypes.Integer: esp->Value = a->Value | b->Value; break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Shl: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; int bits = b->Value; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) << bits; break; case ObjectTypes.Integer: esp->Value = a->Value << bits; break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Shr: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; int bits = b->Value; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&esp->Value) = *((long*)&a->Value) >> bits; break; case ObjectTypes.Integer: esp->Value = a->Value >> bits; break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Shr_Un: { StackObject* b = esp - 1; StackObject* a = esp - 1 - 1; esp = a; int bits = b->Value; switch (a->ObjectType) { case ObjectTypes.Long: *((ulong*)&esp->Value) = *((ulong*)&a->Value) >> bits; break; case ObjectTypes.Integer: *(uint*)&esp->Value = (uint)a->Value >> bits; break; default: throw new NotImplementedException(); } esp++; } break; case OpCodeEnum.Not: { StackObject* a = esp - 1; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&a->Value) = ~*((long*)&a->Value); break; case ObjectTypes.Integer: a->Value = ~a->Value; break; default: throw new NotImplementedException(); } } break; case OpCodeEnum.Neg: { StackObject* a = esp - 1; switch (a->ObjectType) { case ObjectTypes.Long: *((long*)&a->Value) = -*((long*)&a->Value); break; case ObjectTypes.Integer: a->Value = -a->Value; break; case ObjectTypes.Float: *((float*)&a->Value) = -*((float*)&a->Value); break; case ObjectTypes.Double: *((double*)&a->Value) = -*((double*)&a->Value); break; default: throw new NotImplementedException(); } } break; #endregion #region Control Flows case OpCodeEnum.Ret: returned = true; break; case OpCodeEnum.Brtrue: case OpCodeEnum.Brtrue_S: { esp--; bool res = false; switch (esp->ObjectType) { case ObjectTypes.Integer: res = esp->Value != 0; break; case ObjectTypes.Long: res = *(long*)&esp->Value != 0; break; case ObjectTypes.Object: res = mStack[esp->Value] != null; break; } if (res) { ip = ptr + ip->TokenInteger; Free(esp); continue; } else Free(esp); } break; case OpCodeEnum.Brfalse: case OpCodeEnum.Brfalse_S: { esp--; bool res = false; switch (esp->ObjectType) { case ObjectTypes.Null: res = true; break; case ObjectTypes.Integer: res = esp->Value == 0; break; case ObjectTypes.Long: res = *(long*)&esp->Value == 0; break; case ObjectTypes.Object: res = mStack[esp->Value] == null; Free(esp); break; default: Free(esp); break; } if (res) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Beq: case OpCodeEnum.Beq_S: { var b = esp - 1; var a = esp - 1 - 1; bool transfer = false; if (a->ObjectType == b->ObjectType) { switch (a->ObjectType) { case ObjectTypes.Null: transfer = true; break; case ObjectTypes.Integer: transfer = a->Value == b->Value; break; case ObjectTypes.Long: transfer = *(long*)&a->Value == *(long*)&b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value == *(float*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value == *(double*)&b->Value; break; case ObjectTypes.Object: transfer = mStack[a->Value] == mStack[b->Value]; break; default: throw new NotImplementedException(); } } Free(esp - 1); Free(esp - 1 - 1); esp = esp - 1 - 1; if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Bne_Un: case OpCodeEnum.Bne_Un_S: { var b = esp - 1; var a = esp - 1 - 1; bool transfer = false; if (a->ObjectType == b->ObjectType) { switch (a->ObjectType) { case ObjectTypes.Null: transfer = false; break; case ObjectTypes.Integer: transfer = (uint)a->Value != (uint)b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value != *(float*)&b->Value; break; case ObjectTypes.Long: transfer = *(long*)&a->Value != *(long*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value != *(double*)&b->Value; break; case ObjectTypes.Object: transfer = mStack[a->Value] != mStack[b->Value]; break; default: throw new NotImplementedException(); } } else transfer = true; Free(esp - 1); Free(esp - 1 - 1); esp = esp - 1 - 1; if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Bgt: case OpCodeEnum.Bgt_S: { var b = esp - 1; var a = esp - 1 - 1; esp = esp - 1 - 1; bool transfer = false; switch (esp->ObjectType) { case ObjectTypes.Integer: transfer = a->Value > b->Value; break; case ObjectTypes.Long: transfer = *(long*)&a->Value > *(long*)&b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value > *(float*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value > *(double*)&b->Value; break; default: throw new NotImplementedException(); } if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Bgt_Un: case OpCodeEnum.Bgt_Un_S: { var b = esp - 1; var a = esp - 1 - 1; esp = esp - 1 - 1; bool transfer = false; switch (esp->ObjectType) { case ObjectTypes.Integer: transfer = (uint)a->Value > (uint)b->Value; break; case ObjectTypes.Long: transfer = *(ulong*)&a->Value > *(ulong*)&b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value > *(float*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value > *(double*)&b->Value; break; default: throw new NotImplementedException(); } if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Bge: case OpCodeEnum.Bge_S: { var b = esp - 1; var a = esp - 1 - 1; esp = esp - 1 - 1; bool transfer = false; switch (esp->ObjectType) { case ObjectTypes.Integer: transfer = a->Value >= b->Value; break; case ObjectTypes.Long: transfer = *(long*)&a->Value >= *(long*)&b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value >= *(float*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value >= *(double*)&b->Value; break; default: throw new NotImplementedException(); } if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Bge_Un: case OpCodeEnum.Bge_Un_S: { var b = esp - 1; var a = esp - 1 - 1; esp = esp - 1 - 1; bool transfer = false; switch (esp->ObjectType) { case ObjectTypes.Integer: transfer = (uint)a->Value >= (uint)b->Value; break; case ObjectTypes.Long: transfer = *(ulong*)&a->Value >= *(ulong*)&b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value >= *(float*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value >= *(double*)&b->Value; break; default: throw new NotImplementedException(); } if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Blt: case OpCodeEnum.Blt_S: { var b = esp - 1; var a = esp - 1 - 1; esp = esp - 1 - 1; bool transfer = false; switch (esp->ObjectType) { case ObjectTypes.Integer: transfer = a->Value < b->Value; break; case ObjectTypes.Long: transfer = *(long*)&a->Value < *(long*)&b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value < *(float*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value < *(double*)&b->Value; break; default: throw new NotImplementedException(); } if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Blt_Un: case OpCodeEnum.Blt_Un_S: { var b = esp - 1; var a = esp - 1 - 1; esp = esp - 1 - 1; bool transfer = false; switch (esp->ObjectType) { case ObjectTypes.Integer: transfer = (uint)a->Value < (uint)b->Value; break; case ObjectTypes.Long: transfer = *(ulong*)&a->Value < *(ulong*)&b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value < *(float*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value < *(double*)&b->Value; break; default: throw new NotImplementedException(); } if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Ble: case OpCodeEnum.Ble_S: { var b = esp - 1; var a = esp - 1 - 1; esp = esp - 1 - 1; bool transfer = false; switch (esp->ObjectType) { case ObjectTypes.Integer: transfer = a->Value <= b->Value; break; case ObjectTypes.Long: transfer = *(long*)&a->Value <= *(long*)&b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value <= *(float*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value <= *(double*)&b->Value; break; default: throw new NotImplementedException(); } if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Ble_Un: case OpCodeEnum.Ble_Un_S: { var b = esp - 1; var a = esp - 1 - 1; esp = esp - 1 - 1; bool transfer = false; switch (esp->ObjectType) { case ObjectTypes.Integer: transfer = (uint)a->Value <= (uint)b->Value; break; case ObjectTypes.Long: transfer = *(ulong*)&a->Value <= *(ulong*)&b->Value; break; case ObjectTypes.Float: transfer = *(float*)&a->Value <= *(float*)&b->Value; break; case ObjectTypes.Double: transfer = *(double*)&a->Value <= *(double*)&b->Value; break; default: throw new NotImplementedException(); } if (transfer) { ip = ptr + ip->TokenInteger; continue; } } break; case OpCodeEnum.Br_S: case OpCodeEnum.Br: ip = ptr + ip->TokenInteger; continue; case OpCodeEnum.Switch: { var val = (esp - 1)->Value; Free(esp - 1); esp--; var table = method.JumpTables[ip->TokenInteger]; if (val >= 0 && val < table.Length) { ip = ptr + table[val]; continue; } } break; case OpCodeEnum.Leave: case OpCodeEnum.Leave_S: { if (method.ExceptionHandler != null) { ExceptionHandler eh = null; int addr = ip->TokenInteger; var sql = from e in method.ExceptionHandler where addr == e.HandlerEnd + 1 && e.HandlerType == ExceptionHandlerType.Finally || e.HandlerType == ExceptionHandlerType.Fault select e; eh = sql.FirstOrDefault(); if (eh != null) { finallyEndAddress = ip->TokenInteger; ip = ptr + eh.HandlerStart; continue; } } ip = ptr + ip->TokenInteger; continue; } case OpCodeEnum.Endfinally: { ip = ptr + finallyEndAddress; finallyEndAddress = 0; continue; } case OpCodeEnum.Call: case OpCodeEnum.Callvirt: { IMethod m = domain.GetMethod(ip->TokenInteger); if (m == null) { //Irrelevant method int cnt = (int)ip->TokenLong; //Balance the stack for (int i = 0; i < cnt; i++) { Free(esp - 1); esp--; } } else { if (m is ILMethod) { ILMethod ilm = (ILMethod)m; bool processed = false; if (m.IsDelegateInvoke) { var instance = StackObject.ToObject((Minus(esp, m.ParameterCount + 1)), domain, mStack); if (instance is IDelegateAdapter) { esp = ((IDelegateAdapter)instance).ILInvoke(this, esp, mStack); processed = true; } } if (!processed) { if (code == OpCodeEnum.Callvirt) { var objRef = GetObjectAndResolveReference(Minus(esp, ilm.ParameterCount + 1)); if (objRef->ObjectType == ObjectTypes.Null) throw new NullReferenceException(); var obj = mStack[objRef->Value]; if (obj == null) throw new NullReferenceException(); ilm = ((ILTypeInstance)obj).Type.GetVirtualMethod(ilm) as ILMethod; } esp = Execute(ilm, esp, out unhandledException); ValueTypeBasePointer = bp; if (unhandledException) returned = true; } } else { CLRMethod cm = (CLRMethod)m; bool processed = false; if (cm.IsDelegateInvoke) { var instance = StackObject.ToObject((Minus(esp, cm.ParameterCount + 1)), domain, mStack); if (instance is IDelegateAdapter) { esp = ((IDelegateAdapter)instance).ILInvoke(this, esp, mStack); processed = true; } } if (!processed) { var redirect = cm.Redirection; if (redirect != null) esp = redirect(this, esp, mStack, cm, false); else { #if DEBUG if (!allowUnboundCLRMethod) throw new NotSupportedException(cm.ToString() + " is not bound!"); #endif #if UNITY_EDITOR if (System.Threading.Thread.CurrentThread.ManagedThreadId == AppDomain.UnityMainThreadID) #if UNITY_5_5_OR_NEWER UnityEngine.Profiling.Profiler.BeginSample(cm.ToString()); #else UnityEngine.Profiler.BeginSample(cm.ToString()); #endif #endif object result = cm.Invoke(this, esp, mStack); #if UNITY_EDITOR if (System.Threading.Thread.CurrentThread.ManagedThreadId == AppDomain.UnityMainThreadID) #if UNITY_5_5_OR_NEWER UnityEngine.Profiling.Profiler.EndSample(); #else UnityEngine.Profiler.EndSample(); #endif #endif if (result is CrossBindingAdaptorType) result = ((CrossBindingAdaptorType)result).ILInstance; int paramCount = cm.ParameterCount; for (int i = 1; i <= paramCount; i++) { Free(Minus(esp, i)); } esp = Minus(esp, paramCount); if (cm.HasThis) { Free(esp - 1); esp--; } if (cm.ReturnType != AppDomain.VoidType && !cm.IsConstructor) { esp = PushObject(esp, mStack, result, cm.ReturnType.TypeForCLR == typeof(object)); } } } } } } break; #endregion #region FieldOperation case OpCodeEnum.Stfld: { var objRef = GetObjectAndResolveReference(esp - 1 - 1); if (objRef->ObjectType == ObjectTypes.ValueTypeObjectReference) { StackObject* dst = *(StackObject**)&objRef->Value; var ft = domain.GetType(dst->Value); if (ft is ILType) CopyToValueTypeField(dst, (int)ip->TokenLong, esp - 1, mStack); else CopyToValueTypeField(dst, ((CLRType)ft).FieldIndexMapping[(int)ip->TokenLong], esp - 1, mStack); } else { object obj = RetriveObject(objRef, mStack); if (obj != null) { if (obj is ILTypeInstance) { ILTypeInstance instance = obj as ILTypeInstance; StackObject* val = esp - 1; instance.AssignFromStack((int)ip->TokenLong, val, AppDomain, mStack); } else { var t = obj.GetType(); var type = AppDomain.GetType((int)(ip->TokenLong >> 32)); if (type != null) { var val = esp - 1; var fieldToken = (int)ip->TokenLong; var f = ((CLRType)type).GetField(fieldToken); ((CLRType)type).SetFieldValue(fieldToken, ref obj, f.FieldType.CheckCLRTypes(CheckAndCloneValueType(StackObject.ToObject(val, domain, mStack), domain))); //Writeback if (t.IsValueType) { switch (objRef->ObjectType) { case ObjectTypes.Object: break; case ObjectTypes.FieldReference: { var oldObj = mStack[objRef->Value]; int idx = objRef->ValueLow; if (oldObj is ILTypeInstance) { ((ILTypeInstance)oldObj)[idx] = obj; } else { var it = AppDomain.GetType(oldObj.GetType()); ((CLRType)it).SetFieldValue(idx, ref oldObj, obj); } } break; case ObjectTypes.StaticFieldReference: { var it = AppDomain.GetType(objRef->Value); int idx = objRef->ValueLow; if (it is ILType) { ((ILType)it).StaticInstance[idx] = obj; } else { ((CLRType)it).SetStaticFieldValue(idx, obj); } } break; default: throw new NotImplementedException(); } } } else throw new TypeLoadException(); } } else throw new NullReferenceException(); } Free(esp - 1); Free(esp - 1 - 1); esp = esp - 1 - 1; } break; case OpCodeEnum.Ldfld: { StackObject* objRef = GetObjectAndResolveReference(esp - 1); if (objRef->ObjectType == ObjectTypes.ValueTypeObjectReference) { var dst = *(StackObject**)&objRef->Value; var ft = domain.GetType(dst->Value); if (ft is ILType) dst = Minus(dst, (int)ip->TokenLong + 1); else dst = Minus(dst, ((CLRType)ft).FieldIndexMapping[(int)ip->TokenLong] + 1); CopyToStack(objRef, dst, mStack); } else { object obj = RetriveObject(objRef, mStack); Free(esp - 1); if (obj != null) { if (obj is ILTypeInstance) { ILTypeInstance instance = obj as ILTypeInstance; instance.PushToStack((int)ip->TokenLong, esp - 1, AppDomain, mStack); } else { //var t = obj.GetType(); var type = AppDomain.GetType((int)(ip->TokenLong >> 32)); if (type != null) { var token = (int)ip->TokenLong; var ft = ((CLRType)type).GetField(token); var val = ((CLRType)type).GetFieldValue(token, obj); if (val is CrossBindingAdaptorType) val = ((CrossBindingAdaptorType)val).ILInstance; PushObject(esp - 1, mStack, val, ft.FieldType == typeof(object)); } else throw new TypeLoadException(); } } else throw new NullReferenceException(); } } break; case OpCodeEnum.Ldflda: { StackObject* objRef = GetObjectAndResolveReference(esp - 1); if (objRef->ObjectType == ObjectTypes.ValueTypeObjectReference) { var dst = esp - 1; var ft = domain.GetType((int)(ip->TokenLong >> 32)); StackObject* fieldAddr; if (ft is ILType) { fieldAddr = Minus(*(StackObject**)&objRef->Value, (int)ip->TokenLong + 1); } else { fieldAddr = Minus(*(StackObject**)&objRef->Value, ((CLRType)ft).FieldIndexMapping[(int)ip->TokenLong] + 1); } dst->ObjectType = ObjectTypes.StackObjectReference; *(StackObject**)&dst->Value = fieldAddr; } else { object obj = RetriveObject(objRef, mStack); Free(esp - 1); if (obj != null) { if (obj is ILTypeInstance) { ILTypeInstance instance = obj as ILTypeInstance; instance.PushFieldAddress((int)ip->TokenLong, esp - 1, mStack); } else { objRef = esp - 1; objRef->ObjectType = ObjectTypes.FieldReference; objRef->Value = mStack.Count; mStack.Add(obj); objRef->ValueLow = (int)ip->TokenLong; } } else throw new NullReferenceException(); } } break; case OpCodeEnum.Stsfld: { IType type = AppDomain.GetType((int)(ip->TokenLong >> 32)); if (type != null) { if (type is ILType) { ILType t = type as ILType; StackObject* val = esp - 1; t.StaticInstance.AssignFromStack((int)ip->TokenLong, val, AppDomain, mStack); } else { CLRType t = type as CLRType; int idx = (int)ip->TokenLong; var f = t.GetField(idx); StackObject* val = esp - 1; t.SetStaticFieldValue(idx, f.FieldType.CheckCLRTypes(CheckAndCloneValueType(StackObject.ToObject(val, domain, mStack), domain))); } } else throw new TypeLoadException(); Free(esp - 1); esp -= 1; } break; case OpCodeEnum.Ldsfld: { IType type = AppDomain.GetType((int)(ip->TokenLong >> 32)); if (type != null) { if (type is ILType) { ILType t = type as ILType; t.StaticInstance.PushToStack((int)ip->TokenLong, esp, AppDomain, mStack); } else { CLRType t = type as CLRType; int idx = (int)ip->TokenLong; var f = t.GetField(idx); var val = t.GetFieldValue(idx, null); if (val is CrossBindingAdaptorType) val = ((CrossBindingAdaptorType)val).ILInstance; PushObject(esp, mStack, val, f.FieldType == typeof(object)); } } else throw new TypeLoadException(); esp++; } break; case OpCodeEnum.Ldsflda: { int type = (int)(ip->TokenLong >> 32); int fieldIdx = (int)(ip->TokenLong); esp->ObjectType = ObjectTypes.StaticFieldReference; esp->Value = type; esp->ValueLow = fieldIdx; esp++; } break; case OpCodeEnum.Ldtoken: { switch (ip->TokenInteger) { case 0: { IType type = AppDomain.GetType((int)(ip->TokenLong >> 32)); if (type != null) { if (type is ILType) { ILType t = type as ILType; t.StaticInstance.PushToStack((int)ip->TokenLong, esp, AppDomain, mStack); } else throw new NotImplementedException(); } } esp++; break; case 1: { IType type = AppDomain.GetType((int)ip->TokenLong); if (type != null) { esp = PushObject(esp, mStack, type.ReflectionType); } else throw new TypeLoadException(); } break; default: throw new NotImplementedException(); } } break; case OpCodeEnum.Ldftn: { IMethod m = domain.GetMethod(ip->TokenInteger); esp = PushObject(esp, mStack, m); } break; case OpCodeEnum.Ldvirtftn: { IMethod m = domain.GetMethod(ip->TokenInteger); var objRef = esp - 1; if (m is ILMethod) { ILMethod ilm = (ILMethod)m; var obj = mStack[objRef->Value]; m = ((ILTypeInstance)obj).Type.GetVirtualMethod(ilm) as ILMethod; } else { var obj = mStack[objRef->Value]; if (obj is ILTypeInstance) m = ((ILTypeInstance)obj).Type.GetVirtualMethod(m); else if (obj is CrossBindingAdaptorType) { m = ((CrossBindingAdaptorType)obj).ILInstance.Type.BaseType.GetVirtualMethod(m); } } Free(objRef); esp = PushObject(objRef, mStack, m); } break; #endregion #region Compare case OpCodeEnum.Ceq: { StackObject* obj1 = esp - 1 - 1; StackObject* obj2 = esp - 1; bool res = false; if (obj1->ObjectType == obj2->ObjectType) { switch (obj1->ObjectType) { case ObjectTypes.Integer: case ObjectTypes.Float: res = obj1->Value == obj2->Value; break; case ObjectTypes.Object: res = mStack[obj1->Value] == mStack[obj2->Value]; break; case ObjectTypes.FieldReference: res = mStack[obj1->Value] == mStack[obj2->Value] && obj1->ValueLow == obj2->ValueLow; break; case ObjectTypes.Null: res = true; break; default: res = obj1->Value == obj2->Value && obj1->ValueLow == obj2->ValueLow; break; } } else { switch (obj1->ObjectType) { case ObjectTypes.Object: res = mStack[obj1->Value] == null && obj2->ObjectType == ObjectTypes.Null; break; case ObjectTypes.Null: res = obj2->ObjectType == ObjectTypes.Object && mStack[obj2->Value] == null; break; } } Free(esp - 1); Free(esp - 1 - 1); if (res) esp = PushOne(esp - 1 - 1); else esp = PushZero(esp - 1 - 1); } break; case OpCodeEnum.Clt: { StackObject* obj1 = esp - 1 - 1; StackObject* obj2 = esp - 1; bool res = false; switch (obj1->ObjectType) { case ObjectTypes.Integer: res = obj1->Value < obj2->Value; break; case ObjectTypes.Long: res = *(long*)&obj1->Value < *(long*)&obj2->Value; break; case ObjectTypes.Float: res = *(float*)&obj1->Value < *(float*)&obj2->Value; break; case ObjectTypes.Double: res = *(double*)&obj1->Value < *(double*)&obj2->Value; break; default: throw new NotImplementedException(); } if (res) esp = PushOne(esp - 1 - 1); else esp = PushZero(esp - 1 - 1); } break; case OpCodeEnum.Clt_Un: { StackObject* obj1 = esp - 1 - 1; StackObject* obj2 = esp - 1; bool res = false; switch (obj1->ObjectType) { case ObjectTypes.Integer: res = (uint)obj1->Value < (uint)obj2->Value && obj2->ObjectType != ObjectTypes.Null; break; case ObjectTypes.Long: res = (ulong)*(long*)&obj1->Value < (ulong)*(long*)&obj2->Value && obj2->ObjectType != ObjectTypes.Null; break; case ObjectTypes.Float: res = *(float*)&obj1->Value < *(float*)&obj2->Value && obj2->ObjectType != ObjectTypes.Null; break; case ObjectTypes.Double: res = *(double*)&obj1->Value < *(double*)&obj2->Value && obj2->ObjectType != ObjectTypes.Null; break; default: throw new NotImplementedException(); } if (res) esp = PushOne(esp - 1 - 1); else esp = PushZero(esp - 1 - 1); } break; case OpCodeEnum.Cgt: { StackObject* obj1 = esp - 1 - 1; StackObject* obj2 = esp - 1; bool res = false; switch (obj1->ObjectType) { case ObjectTypes.Integer: res = obj1->Value > obj2->Value || obj2->ObjectType == ObjectTypes.Null; break; case ObjectTypes.Long: res = *(long*)&obj1->Value > *(long*)&obj2->Value || obj2->ObjectType == ObjectTypes.Null; break; case ObjectTypes.Float: res = *(float*)&obj1->Value > *(float*)&obj2->Value || obj2->ObjectType == ObjectTypes.Null; break; case ObjectTypes.Double: res = *(double*)&obj1->Value > *(double*)&obj2->Value || obj2->ObjectType == ObjectTypes.Null; break; default: throw new NotImplementedException(); } if (res) esp = PushOne(esp - 1 - 1); else esp = PushZero(esp - 1 - 1); } break; case OpCodeEnum.Cgt_Un: { StackObject* obj1 = esp - 1 - 1; StackObject* obj2 = esp - 1; bool res = false; switch (obj1->ObjectType) { case ObjectTypes.Integer: res = ((uint)obj1->Value > (uint)obj2->Value) || obj2->ObjectType == ObjectTypes.Null; break; case ObjectTypes.Long: res = (ulong)*(long*)&obj1->Value > (ulong)*(long*)&obj2->Value || obj2->ObjectType == ObjectTypes.Null; break; case ObjectTypes.Float: res = *(float*)&obj1->Value > *(float*)&obj2->Value || obj2->ObjectType == ObjectTypes.Null; break; case ObjectTypes.Double: res = *(double*)&obj1->Value > *(double*)&obj2->Value || obj2->ObjectType == ObjectTypes.Null; break; case ObjectTypes.Object: res = mStack[obj1->Value] != null && obj2->ObjectType == ObjectTypes.Null; break; case ObjectTypes.Null: res = false; break; default: throw new NotImplementedException(); } if (res) esp = PushOne(esp - 1 - 1); else esp = PushZero(esp - 1 - 1); } break; #endregion #region Initialization & Instantiation case OpCodeEnum.Newobj: { IMethod m = domain.GetMethod(ip->TokenInteger); if (m is ILMethod) { ILType type = m.DeclearingType as ILType; if (type.IsDelegate) { var objRef = GetObjectAndResolveReference(esp - 1 - 1); var mi = (IMethod)mStack[(esp - 1)->Value]; object ins; if (objRef->ObjectType == ObjectTypes.Null) ins = null; else ins = mStack[objRef->Value]; Free(esp - 1); Free(esp - 1 - 1); esp = esp - 1 - 1; object dele; if (mi is ILMethod) { if (ins != null) { dele = ((ILTypeInstance)ins).GetDelegateAdapter((ILMethod)mi); if (dele == null) dele = domain.DelegateManager.FindDelegateAdapter((ILTypeInstance)ins, (ILMethod)mi); } else { if (((ILMethod)mi).DelegateAdapter == null) { ((ILMethod)mi).DelegateAdapter = domain.DelegateManager.FindDelegateAdapter(null, (ILMethod)mi); } dele = ((ILMethod)mi).DelegateAdapter; } } else { throw new NotImplementedException(); } esp = PushObject(esp, mStack, dele); } else { var a = esp - m.ParameterCount; StackObject* objRef; ILTypeInstance obj = null; bool isValueType = type.IsValueType; if (isValueType) { stack.AllocValueType(esp, type); objRef = esp + 1; objRef->ObjectType = ObjectTypes.StackObjectReference; *(StackObject**)&objRef->Value = esp; objRef++; } else { obj = type.Instantiate(false); objRef = PushObject(esp, mStack, obj);//this parameter for constructor } esp = objRef; for (int i = 0; i < m.ParameterCount; i++) { CopyToStack(esp, a + i, mStack); esp++; } esp = Execute((ILMethod)m, esp, out unhandledException); ValueTypeBasePointer = bp; if (isValueType) { var ins = objRef - 1 - 1; *a = *ins; esp = a + 1; } else esp = PushObject(a, mStack, obj);//new constructedObj } if (unhandledException) returned = true; } else { CLRMethod cm = (CLRMethod)m; //Means new object(); if (cm == null) { esp = PushObject(esp, mStack, new object()); } else { if (cm.DeclearingType.IsDelegate) { var objRef = GetObjectAndResolveReference(esp - 1 - 1); var mi = (IMethod)mStack[(esp - 1)->Value]; object ins; if (objRef->ObjectType == ObjectTypes.Null) ins = null; else ins = mStack[objRef->Value]; Free(esp - 1); Free(esp - 1 - 1); esp = esp - 1 - 1; object dele; if (mi is ILMethod) { if (ins != null) { dele = ((ILTypeInstance)ins).GetDelegateAdapter((ILMethod)mi); if (dele == null) dele = domain.DelegateManager.FindDelegateAdapter((ILTypeInstance)ins, (ILMethod)mi); } else { if (((ILMethod)mi).DelegateAdapter == null) { ((ILMethod)mi).DelegateAdapter = domain.DelegateManager.FindDelegateAdapter(null, (ILMethod)mi); } dele = ((ILMethod)mi).DelegateAdapter; } } else { if (ins is ILTypeInstance) ins = ((ILTypeInstance)ins).CLRInstance; dele = Delegate.CreateDelegate(cm.DeclearingType.TypeForCLR, ins, ((CLRMethod)mi).MethodInfo); } esp = PushObject(esp, mStack, dele); } else { var redirect = cm.Redirection; if (redirect != null) esp = redirect(this, esp, mStack, cm, true); else { object result = cm.Invoke(this, esp, mStack, true); int paramCount = cm.ParameterCount; for (int i = 1; i <= paramCount; i++) { Free(esp - i); } esp = Minus(esp, paramCount); esp = PushObject(esp, mStack, result);//new constructedObj } } } } } break; case OpCodeEnum.Constrained: { var objRef = esp - 1; var obj = GetObjectAndResolveReference(objRef); var type = domain.GetType(ip->TokenInteger); if (type != null) { if (type is ILType) { var t = (ILType)type; if (t.IsEnum) { ILEnumTypeInstance ins = new ILEnumTypeInstance(t); switch (obj->ObjectType) { case ObjectTypes.FieldReference: { var owner = mStack[obj->Value] as ILTypeInstance; int idx = obj->ValueLow; Free(objRef); owner.PushToStack(idx, objRef, AppDomain, mStack); ins.AssignFromStack(0, objRef, AppDomain, mStack); ins.Boxed = true; } break; case ObjectTypes.StaticFieldReference: { var st = AppDomain.GetType(obj->Value) as ILType; int idx = obj->ValueLow; Free(objRef); st.StaticInstance.PushToStack(idx, objRef, AppDomain, mStack); ins.AssignFromStack(0, objRef, AppDomain, mStack); ins.Boxed = true; } break; case ObjectTypes.ArrayReference: { var arr = mStack[obj->Value]; var idx = obj->ValueLow; Free(objRef); LoadFromArrayReference(arr, idx, objRef, t, mStack); ins.AssignFromStack(0, objRef, AppDomain, mStack); ins.Boxed = true; } break; default: ins.AssignFromStack(0, obj, AppDomain, mStack); ins.Boxed = true; break; } esp = PushObject(esp - 1, mStack, ins); } else { //Nothing to do for normal IL Types } } else { var tt = type.TypeForCLR; if (tt.IsEnum) { esp = PushObject(esp - 1, mStack, Enum.ToObject(tt, StackObject.ToObject(obj, AppDomain, mStack))); } else if (tt.IsPrimitive) { esp = PushObject(esp - 1, mStack, tt.CheckCLRTypes(StackObject.ToObject(obj, AppDomain, mStack))); } else { //Nothing to do for other CLR types } } } else throw new NullReferenceException(); } break; case OpCodeEnum.Box: { var obj = esp - 1; var type = domain.GetType(ip->TokenInteger); if (type != null) { if (type is ILType) { if (((ILType)type).IsEnum) { ILEnumTypeInstance ins = new Intepreter.ILEnumTypeInstance((ILType)type); ins.AssignFromStack(0, obj, AppDomain, mStack); ins.Boxed = true; esp = PushObject(obj, mStack, ins, true); } else { switch (obj->ObjectType) { case ObjectTypes.Null: break; case ObjectTypes.ValueTypeObjectReference: { ILTypeInstance ins = ((ILType)type).Instantiate(false); ins.AssignFromStack(obj, domain, mStack); FreeStackValueType(obj); esp = PushObject(obj, mStack, ins, true); } break; default: { var val = mStack[obj->Value]; Free(obj); ILTypeInstance ins = (ILTypeInstance)val; if (ins != null) { if (ins.IsValueType) { ins.Boxed = true; } esp = PushObject(obj, mStack, ins, true); } else { esp = PushNull(obj); } } break; } } } else { if (type.TypeForCLR.IsPrimitive) { var t = type.TypeForCLR; if (t == typeof(int)) { switch (obj->ObjectType) { case ObjectTypes.Integer: esp = PushObject(obj, mStack, obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, 0, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(bool)) { switch (obj->ObjectType) { case ObjectTypes.Integer: esp = PushObject(obj, mStack, (obj->Value == 1), true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, false, true); break; case ObjectTypes.Object: break; default: throw new NotImplementedException(); } } else if (t == typeof(byte)) { switch (obj->ObjectType) { case ObjectTypes.Integer: esp = PushObject(obj, mStack, (byte)obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, 0L, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(short)) { switch (obj->ObjectType) { case ObjectTypes.Integer: esp = PushObject(obj, mStack, (short)obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, (short)0, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(long)) { switch (obj->ObjectType) { case ObjectTypes.Long: esp = PushObject(obj, mStack, *(long*)&obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, 0L, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(float)) { switch (obj->ObjectType) { case ObjectTypes.Float: esp = PushObject(obj, mStack, *(float*)&obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, 0f, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(double)) { switch (obj->ObjectType) { case ObjectTypes.Double: esp = PushObject(obj, mStack, *(double*)&obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, 0.0, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(char)) { switch (obj->ObjectType) { case ObjectTypes.Integer: esp = PushObject(obj, mStack, (char)obj->Value, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(uint)) { switch (obj->ObjectType) { case ObjectTypes.Integer: esp = PushObject(obj, mStack, (uint)obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, (uint)0, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(ushort)) { switch (obj->ObjectType) { case ObjectTypes.Integer: esp = PushObject(obj, mStack, (ushort)obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, (ushort)0, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(ulong)) { switch (obj->ObjectType) { case ObjectTypes.Long: esp = PushObject(obj, mStack, *(ulong*)&obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, (ulong)0, true); break; default: throw new NotImplementedException(); } } else if (t == typeof(sbyte)) { switch (obj->ObjectType) { case ObjectTypes.Integer: esp = PushObject(obj, mStack, (sbyte)obj->Value, true); break; case ObjectTypes.Null: esp = PushObject(obj, mStack, (sbyte)0, true); break; default: throw new NotImplementedException(); } } else throw new NotImplementedException(); } else if (type.TypeForCLR.IsEnum) { esp = PushObject(obj, mStack, Enum.ToObject(type.TypeForCLR, StackObject.ToObject(obj, AppDomain, mStack)), true); } else { if(obj->ObjectType== ObjectTypes.ValueTypeObjectReference) { var dst = *(StackObject**)&obj->Value; var vt = domain.GetType(dst->Value); if (vt != type) throw new InvalidCastException(); object ins = ((CLRType)vt).ValueTypeBinder.ToObject(dst, mStack); FreeStackValueType(obj); esp = PushObject(obj, mStack, ins, true); } //nothing to do for CLR type boxing } } } else throw new NullReferenceException(); } break; case OpCodeEnum.Unbox: case OpCodeEnum.Unbox_Any: { var objRef = esp - 1; if (objRef->ObjectType == ObjectTypes.Object) { object obj = mStack[objRef->Value]; Free(objRef); if (obj != null) { var t = domain.GetType(ip->TokenInteger); if (t != null) { var type = t.TypeForCLR; if ((t is CLRType) && type.IsPrimitive) { if (type == typeof(int)) { int val = obj.ToInt32(); objRef->ObjectType = ObjectTypes.Integer; objRef->Value = val; } else if (type == typeof(bool)) { bool val = (bool)obj; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = val ? 1 : 0; } else if (type == typeof(short)) { short val = obj.ToInt16(); objRef->ObjectType = ObjectTypes.Integer; objRef->Value = val; } else if (type == typeof(long)) { long val = obj.ToInt64(); objRef->ObjectType = ObjectTypes.Long; *(long*)&objRef->Value = val; } else if (type == typeof(float)) { float val = obj.ToFloat(); objRef->ObjectType = ObjectTypes.Float; *(float*)&objRef->Value = val; } else if (type == typeof(byte)) { byte val = (byte)obj; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = val; } else if (type == typeof(double)) { double val = obj.ToDouble(); objRef->ObjectType = ObjectTypes.Double; *(double*)&objRef->Value = val; } else if (type == typeof(char)) { char val = (char)obj; objRef->ObjectType = ObjectTypes.Integer; *(char*)&objRef->Value = val; } else if (type == typeof(uint)) { uint val = (uint)obj; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = (int)val; } else if (type == typeof(ushort)) { ushort val = (ushort)obj; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = val; } else if (type == typeof(ulong)) { ulong val = (ulong)obj; objRef->ObjectType = ObjectTypes.Long; *(ulong*)&objRef->Value = val; } else if (type == typeof(sbyte)) { sbyte val = (sbyte)obj; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = val; } else throw new NotImplementedException(); } else if (t.IsValueType) { if (obj is ILTypeInstance) { var res = ((ILTypeInstance)obj); if (res is ILEnumTypeInstance) { res.PushToStack(0, objRef, AppDomain, mStack); } else { if (res.Boxed) { res = res.Clone(); res.Boxed = false; } PushObject(objRef, mStack, res); } } else PushObject(objRef, mStack, obj); } else { PushObject(objRef, mStack, obj); } } else throw new TypeLoadException(); } else throw new NullReferenceException(); } else if (objRef->ObjectType < ObjectTypes.StackObjectReference) { //Nothing to do with primitive types } else throw new InvalidCastException(); } break; case OpCodeEnum.Initobj: { var objRef = GetObjectAndResolveReference(esp - 1); var type = domain.GetType(ip->TokenInteger); if (type is ILType) { ILType it = (ILType)type; if (it.IsValueType) { switch (objRef->ObjectType) { case ObjectTypes.Null: throw new NullReferenceException(); case ObjectTypes.ValueTypeObjectReference: stack.ClearValueTypeObject(type, *(StackObject**)&objRef->Value); break; case ObjectTypes.Object: { var obj = mStack[objRef->Value]; if (obj != null) { if (obj is ILTypeInstance) { ILTypeInstance instance = obj as ILTypeInstance; instance.Clear(); } else throw new NotSupportedException(); } else throw new NullReferenceException(); } break; default: throw new NotImplementedException(); } Free(esp - 1); esp--; } else { PushNull(esp); switch (objRef->ObjectType) { case ObjectTypes.StaticFieldReference: { var t = AppDomain.GetType(objRef->Value) as ILType; t.StaticInstance.AssignFromStack(objRef->ValueLow, esp, AppDomain, mStack); } break; case ObjectTypes.FieldReference: { var instance = mStack[objRef->Value] as ILTypeInstance; instance.AssignFromStack(objRef->ValueLow, esp, AppDomain, mStack); Free(esp - 1); esp--; } break; default: { if (objRef->ObjectType >= ObjectTypes.Object) mStack[objRef->Value] = null; else PushNull(objRef); } break; } } } else { if (objRef->ObjectType == ObjectTypes.ValueTypeObjectReference) { stack.ClearValueTypeObject(type, *(StackObject**)&objRef->Value); } Free(esp - 1); esp--; } } break; case OpCodeEnum.Isinst: { var objRef = esp - 1; var type = domain.GetType(ip->TokenInteger); if (type != null) { objRef = GetObjectAndResolveReference(objRef); if (objRef->ObjectType <= ObjectTypes.Double) { var tclr = type.TypeForCLR; switch (objRef->ObjectType) { case ObjectTypes.Integer: { if (tclr != typeof(int) && tclr != typeof(bool) && tclr != typeof(short) && tclr != typeof(byte) && tclr != typeof(ushort) && tclr !=typeof(uint)) { objRef->ObjectType = ObjectTypes.Null; objRef->Value = -1; objRef->ValueLow = 0; } } break; case ObjectTypes.Long: { if (tclr != typeof(long) && tclr != typeof(ulong)) { objRef->ObjectType = ObjectTypes.Null; objRef->Value = -1; objRef->ValueLow = 0; } } break; case ObjectTypes.Float: { if (tclr != typeof(float)) { objRef->ObjectType = ObjectTypes.Null; objRef->Value = -1; objRef->ValueLow = 0; } } break; case ObjectTypes.Double: { if (tclr != typeof(double)) { objRef->ObjectType = ObjectTypes.Null; objRef->Value = -1; objRef->ValueLow = 0; } } break; case ObjectTypes.Null: objRef->ObjectType = ObjectTypes.Null; objRef->Value = -1; objRef->ValueLow = 0; break; } } else { var obj = RetriveObject(objRef, mStack); Free(objRef); if (obj != null) { if (obj is ILTypeInstance) { if (((ILTypeInstance)obj).CanAssignTo(type)) { esp = PushObject(objRef, mStack, obj); } else { #if !DEBUG objRef->ObjectType = ObjectTypes.Null; objRef->Value = -1; objRef->ValueLow = 0; #endif } } else { if (type.TypeForCLR.IsAssignableFrom(obj.GetType())) { esp = PushObject(objRef, mStack, obj, true); } else { #if !DEBUG objRef->ObjectType = ObjectTypes.Null; objRef->Value = -1; objRef->ValueLow = 0; #endif } } } else { #if !DEBUG objRef->ObjectType = ObjectTypes.Null; objRef->Value = -1; objRef->ValueLow = 0; #endif } } } else throw new NullReferenceException(); } break; #endregion #region Array case OpCodeEnum.Newarr: { var cnt = (esp - 1); var type = domain.GetType(ip->TokenInteger); object arr = null; if (type != null) { if (type.TypeForCLR != typeof(ILTypeInstance)) { if (type is CLRType) { arr = ((CLRType)type).CreateArrayInstance(cnt->Value); } else { arr = Array.CreateInstance(type.TypeForCLR, cnt->Value); } //Register Type AppDomain.GetType(arr.GetType()); } else { arr = new ILTypeInstance[cnt->Value]; } } cnt->ObjectType = ObjectTypes.Object; cnt->Value = mStack.Count; mStack.Add(arr); } break; case OpCodeEnum.Stelem_Ref: case OpCodeEnum.Stelem_Any: { var val = GetObjectAndResolveReference(esp - 1); var idx = esp - 1 - 1; var arrRef = esp - 1 - 1 - 1; Array arr = mStack[arrRef->Value] as Array; if (arr is object[]) { switch (val->ObjectType) { case ObjectTypes.Null: arr.SetValue(null, idx->Value); break; case ObjectTypes.Object: ArraySetValue(arr, mStack[val->Value], idx->Value); break; case ObjectTypes.Integer: arr.SetValue(val->Value, idx->Value); break; case ObjectTypes.Long: arr.SetValue(*(long*)&val->Value, idx->Value); break; case ObjectTypes.Float: arr.SetValue(*(float*)&val->Value, idx->Value); break; case ObjectTypes.Double: arr.SetValue(*(double*)&val->Value, idx->Value); break; default: throw new NotImplementedException(); } } else { switch (val->ObjectType) { case ObjectTypes.Object: ArraySetValue(arr, mStack[val->Value], idx->Value); break; case ObjectTypes.Integer: { StoreIntValueToArray(arr, val, idx); } break; case ObjectTypes.Long: { if (arr is long[]) { ((long[])arr)[idx->Value] = *(long*)&val->Value; } else { ((ulong[])arr)[idx->Value] = *(ulong*)&val->Value; } } break; case ObjectTypes.Float: { ((float[])arr)[idx->Value] = *(float*)&val->Value; } break; case ObjectTypes.Double: { ((double[])arr)[idx->Value] = *(double*)&val->Value; } break; default: throw new NotImplementedException(); } } Free(esp - 1); Free(esp - 1 - 1); Free(esp - 1 - 1 - 1); esp = esp - 1 - 1 - 1; } break; case OpCodeEnum.Ldelem_Ref: case OpCodeEnum.Ldelem_Any: { var idx = esp - 1; var arrRef = esp - 1 - 1; Array arr = mStack[arrRef->Value] as Array; object val = arr.GetValue(idx->Value); if (val is CrossBindingAdaptorType) val = ((CrossBindingAdaptorType)val).ILInstance; Free(esp - 1); Free(esp - 1 - 1); esp = PushObject(esp - 1 - 1, mStack, val); } break; case OpCodeEnum.Stelem_I1: { var val = esp - 1; var idx = esp - 1 - 1; var arrRef = esp - 1 - 1 - 1; byte[] arr = mStack[arrRef->Value] as byte[]; if (arr != null) { arr[idx->Value] = (byte)val->Value; } else { bool[] arr2 = mStack[arrRef->Value] as bool[]; if (arr2 != null) { arr2[idx->Value] = val->Value == 1; } else { sbyte[] arr3 = mStack[arrRef->Value] as sbyte[]; arr3[idx->Value] = (sbyte)val->Value; } } Free(esp - 1); Free(esp - 1 - 1); Free(esp - 1 - 1 - 1); esp = esp - 1 - 1 - 1; } break; case OpCodeEnum.Ldelem_I1: { var idx = esp - 1; var arrRef = esp - 1 - 1; bool[] arr = mStack[arrRef->Value] as bool[]; int val; if (arr != null) val = arr[idx->Value] ? 1 : 0; else { sbyte[] arr2 = mStack[arrRef->Value] as sbyte[]; val = arr2[idx->Value]; } Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.Integer; arrRef->Value = val; esp -= 1; } break; case OpCodeEnum.Ldelem_U1: { var idx = (esp - 1); var arrRef = esp - 1 - 1; byte[] arr = mStack[arrRef->Value] as byte[]; int val; if (arr != null) val = arr[idx->Value]; else { bool[] arr2 = mStack[arrRef->Value] as bool[]; val = arr2[idx->Value] ? 1 : 0; } Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.Integer; arrRef->Value = val; esp -= 1; } break; case OpCodeEnum.Stelem_I2: { var val = esp - 1; var idx = esp - 1 - 1; var arrRef = esp - 1 - 1 - 1; short[] arr = mStack[arrRef->Value] as short[]; if (arr != null) { arr[idx->Value] = (short)val->Value; } else { ushort[] arr2 = mStack[arrRef->Value] as ushort[]; if (arr2 != null) { arr2[idx->Value] = (ushort)val->Value; } else { char[] arr3 = mStack[arrRef->Value] as char[]; arr3[idx->Value] = (char)val->Value; } } Free(esp - 1); Free(esp - 1 - 1); Free(esp - 1 - 1 - 1); esp = esp - 1 - 1 - 1; } break; case OpCodeEnum.Ldelem_I2: { var idx = (esp - 1)->Value; var arrRef = esp - 1 - 1; short[] arr = mStack[arrRef->Value] as short[]; int val = 0; if (arr != null) { val = arr[idx]; } else { char[] arr2 = mStack[arrRef->Value] as char[]; val = arr2[idx]; } Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.Integer; arrRef->Value = val; esp -= 1; } break; case OpCodeEnum.Ldelem_U2: { var idx = (esp - 1)->Value; var arrRef = esp - 1 - 1; ushort[] arr = mStack[arrRef->Value] as ushort[]; int val = 0; if (arr != null) { val = arr[idx]; } else { char[] arr2 = mStack[arrRef->Value] as char[]; val = arr2[idx]; } Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.Integer; arrRef->Value = val; esp -= 1; } break; case OpCodeEnum.Stelem_I4: { var val = esp - 1; var idx = esp - 1 - 1; var arrRef = esp - 1 - 1 - 1; int[] arr = mStack[arrRef->Value] as int[]; if (arr != null) { arr[idx->Value] = val->Value; } else { uint[] arr2 = mStack[arrRef->Value] as uint[]; arr2[idx->Value] = (uint)val->Value; } Free(esp - 1); Free(esp - 1 - 1); Free(esp - 1 - 1 - 1); esp = esp - 1 - 1 - 1; } break; case OpCodeEnum.Ldelem_I4: { var idx = (esp - 1)->Value; var arrRef = esp - 1 - 1; int[] arr = mStack[arrRef->Value] as int[]; Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.Integer; arrRef->Value = arr[idx]; esp -= 1; } break; case OpCodeEnum.Ldelem_U4: { var idx = (esp - 1)->Value; var arrRef = esp - 1 - 1; uint[] arr = mStack[arrRef->Value] as uint[]; Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.Integer; arrRef->Value = (int)arr[idx]; esp -= 1; } break; case OpCodeEnum.Stelem_I8: { var val = esp - 1; var idx = esp - 1 - 1; var arrRef = esp - 1 - 1 - 1; long[] arr = mStack[arrRef->Value] as long[]; if (arr != null) { arr[idx->Value] = *(long*)&val->Value; } else { ulong[] arr2 = mStack[arrRef->Value] as ulong[]; arr2[idx->Value] = *(ulong*)&val->Value; } Free(esp - 1); Free(esp - 1 - 1); Free(esp - 1 - 1 - 1); esp = esp - 1 - 1 - 1; } break; case OpCodeEnum.Ldelem_I8: { var idx = esp - 1; var arrRef = esp - 1 - 1; long[] arr = mStack[arrRef->Value] as long[]; long val; if (arr != null) val = arr[idx->Value]; else { ulong[] arr2 = mStack[arrRef->Value] as ulong[]; val = (long)arr2[idx->Value]; } Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.Long; *(long*)&arrRef->Value = val; esp -= 1; } break; case OpCodeEnum.Stelem_R4: { var val = esp - 1; var idx = esp - 1 - 1; var arrRef = esp - 1 - 1 - 1; float[] arr = mStack[arrRef->Value] as float[]; arr[idx->Value] = *(float*)&val->Value; Free(esp - 1); Free(esp - 1 - 1); Free(esp - 1 - 1 - 1); esp = esp - 1 - 1 - 1; } break; case OpCodeEnum.Ldelem_R4: { var idx = (esp - 1)->Value; var arrRef = esp - 1 - 1; float[] arr = mStack[arrRef->Value] as float[]; Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.Float; *(float*)&arrRef->Value = arr[idx]; esp -= 1; } break; case OpCodeEnum.Stelem_R8: { var val = esp - 1; var idx = esp - 1 - 1; var arrRef = esp - 1 - 1 - 1; double[] arr = mStack[arrRef->Value] as double[]; arr[idx->Value] = *(double*)&val->Value; Free(esp - 1); Free(esp - 1 - 1); Free(esp - 1 - 1 - 1); esp = esp - 1 - 1 - 1; } break; case OpCodeEnum.Ldelem_R8: { var idx = (esp - 1)->Value; var arrRef = esp - 1 - 1; double[] arr = mStack[arrRef->Value] as double[]; Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.Double; *(double*)&arrRef->Value = arr[idx]; esp -= 1; } break; case OpCodeEnum.Ldlen: { var arrRef = esp - 1; Array arr = mStack[arrRef->Value] as Array; Free(esp - 1); arrRef->ObjectType = ObjectTypes.Integer; arrRef->Value = arr.Length; } break; case OpCodeEnum.Ldelema: { var arrRef = esp - 1 - 1; var idx = (esp - 1)->Value; Array arr = mStack[arrRef->Value] as Array; Free(esp - 1); Free(esp - 1 - 1); arrRef->ObjectType = ObjectTypes.ArrayReference; arrRef->Value = mStack.Count; mStack.Add(arr); arrRef->ValueLow = idx; esp--; } break; #endregion #region Conversion case OpCodeEnum.Conv_U1: case OpCodeEnum.Conv_Ovf_U1: case OpCodeEnum.Conv_Ovf_U1_Un: { var obj = esp - 1; int val; switch (obj->ObjectType) { case ObjectTypes.Long: case ObjectTypes.Integer: val = (byte)obj->Value; break; case ObjectTypes.Float: val = (byte)*(float*)&obj->Value; break; case ObjectTypes.Double: val = (byte)*(double*)&obj->Value; break; default: throw new NotImplementedException(); } obj->ObjectType = ObjectTypes.Integer; obj->Value = val; obj->ValueLow = 0; } break; case OpCodeEnum.Conv_I1: case OpCodeEnum.Conv_Ovf_I1: case OpCodeEnum.Conv_Ovf_I1_Un: { var obj = esp - 1; int val; switch (obj->ObjectType) { case ObjectTypes.Long: case ObjectTypes.Integer: val = (sbyte)obj->Value; break; case ObjectTypes.Float: val = (sbyte)*(float*)&obj->Value; break; case ObjectTypes.Double: val = (sbyte)*(double*)&obj->Value; break; default: throw new NotImplementedException(); } obj->ObjectType = ObjectTypes.Integer; obj->Value = val; obj->ValueLow = 0; } break; case OpCodeEnum.Conv_U2: case OpCodeEnum.Conv_Ovf_U2: case OpCodeEnum.Conv_Ovf_U2_Un: { var obj = esp - 1; int val; switch (obj->ObjectType) { case ObjectTypes.Long: case ObjectTypes.Integer: val = (ushort)obj->Value; break; case ObjectTypes.Float: val = (ushort)*(float*)&obj->Value; break; case ObjectTypes.Double: val = (ushort)*(double*)&obj->Value; break; default: throw new NotImplementedException(); } obj->ObjectType = ObjectTypes.Integer; obj->Value = val; obj->ValueLow = 0; } break; case OpCodeEnum.Conv_I2: case OpCodeEnum.Conv_Ovf_I2: case OpCodeEnum.Conv_Ovf_I2_Un: { var obj = esp - 1; int val; switch (obj->ObjectType) { case ObjectTypes.Long: case ObjectTypes.Integer: val = (short)(obj->Value); break; case ObjectTypes.Float: val = (short)*(float*)&obj->Value; break; case ObjectTypes.Double: val = (short)*(double*)&obj->Value; break; default: throw new NotImplementedException(); } obj->ObjectType = ObjectTypes.Integer; obj->Value = val; obj->ValueLow = 0; } break; case OpCodeEnum.Conv_U4: case OpCodeEnum.Conv_Ovf_U4: case OpCodeEnum.Conv_Ovf_U4_Un: { var obj = esp - 1; uint val; switch (obj->ObjectType) { case ObjectTypes.Long: val = (uint)*(long*)&obj->Value; break; case ObjectTypes.Integer: val = (uint)obj->Value; break; case ObjectTypes.Float: val = (uint)*(float*)&obj->Value; break; case ObjectTypes.Double: val = (uint)*(double*)&obj->Value; break; default: throw new NotImplementedException(); } obj->ObjectType = ObjectTypes.Integer; obj->Value = (int)val; obj->ValueLow = 0; } break; case OpCodeEnum.Conv_I4: case OpCodeEnum.Conv_Ovf_I: case OpCodeEnum.Conv_Ovf_I_Un: case OpCodeEnum.Conv_Ovf_I4: case OpCodeEnum.Conv_Ovf_I4_Un: { var obj = esp - 1; int val; switch (obj->ObjectType) { case ObjectTypes.Long: val = (int)*(long*)&obj->Value; break; case ObjectTypes.Float: val = (int)*(float*)&obj->Value; break; case ObjectTypes.Double: val = (int)*(double*)&obj->Value; break; case ObjectTypes.Integer: val = obj->Value; break; default: throw new NotImplementedException(); } obj->ObjectType = ObjectTypes.Integer; obj->Value = val; } break; case OpCodeEnum.Conv_U8: case OpCodeEnum.Conv_I8: case OpCodeEnum.Conv_Ovf_I8: case OpCodeEnum.Conv_Ovf_I8_Un: case OpCodeEnum.Conv_Ovf_U8: case OpCodeEnum.Conv_Ovf_U8_Un: { var obj = esp - 1; long val; switch (obj->ObjectType) { case ObjectTypes.Integer: val = obj->Value; break; case ObjectTypes.Long: ip++; continue; case ObjectTypes.Float: val = (long)*(float*)&obj->Value; break; case ObjectTypes.Double: val = (long)*(double*)&obj->Value; break; default: throw new NotImplementedException(); } obj->ObjectType = ObjectTypes.Long; *(long*)(&obj->Value) = val; } break; case OpCodeEnum.Conv_R4: { var obj = esp - 1; float val; switch (obj->ObjectType) { case ObjectTypes.Long: val = (float)*(long*)&obj->Value; break; case ObjectTypes.Float: ip++; continue; case ObjectTypes.Double: val = (float)*(double*)&obj->Value; break; case ObjectTypes.Integer: val = obj->Value; break; default: throw new NotImplementedException(); } obj->ObjectType = ObjectTypes.Float; *(float*)&obj->Value = val; } break; case OpCodeEnum.Conv_R8: { var obj = esp - 1; double val; switch (obj->ObjectType) { case ObjectTypes.Long: val = (double)*(long*)&obj->Value; break; case ObjectTypes.Float: val = *(float*)&obj->Value; break; case ObjectTypes.Integer: val = obj->Value; break; case ObjectTypes.Double: ip++; continue; default: throw new NotImplementedException(); } obj->ObjectType = ObjectTypes.Double; *(double*)&obj->Value = val; } break; case OpCodeEnum.Conv_R_Un: { var obj = esp - 1; bool isDouble = false; float val = 0; double val2 = 0; switch (obj->ObjectType) { case ObjectTypes.Long: val2 = (double)*(ulong*)&obj->Value; isDouble = true; break; case ObjectTypes.Float: ip++; continue; case ObjectTypes.Integer: val = (uint)obj->Value; break; case ObjectTypes.Double: ip++; continue; default: throw new NotImplementedException(); } if (isDouble) { obj->ObjectType = ObjectTypes.Double; *(double*)&obj->Value = val2; } else { obj->ObjectType = ObjectTypes.Float; *(float*)&obj->Value = val; } } break; #endregion #region Stack operation case OpCodeEnum.Pop: { Free(esp - 1); esp--; } break; case OpCodeEnum.Dup: { var obj = esp - 1; *esp = *obj; if (esp->ObjectType >= ObjectTypes.Object) { esp->Value = mStack.Count; mStack.Add(mStack[obj->Value]); } esp++; } break; #endregion case OpCodeEnum.Throw: { var obj = GetObjectAndResolveReference(esp - 1); var ex = mStack[obj->Value] as Exception; Free(obj); esp--; throw ex; } case OpCodeEnum.Nop: case OpCodeEnum.Volatile: case OpCodeEnum.Castclass: break; default: throw new NotSupportedException("Not supported opcode " + code); } ip++; } catch (Exception ex) { if (method.ExceptionHandler != null) { int addr = (int)(ip - ptr); var eh = GetCorrespondingExceptionHandler(method, ex, addr, ExceptionHandlerType.Catch, true); if (eh == null) { eh = GetCorrespondingExceptionHandler(method, ex, addr, ExceptionHandlerType.Catch, false); } if (eh != null) { if (ex is ILRuntimeException) { ILRuntimeException ire = (ILRuntimeException)ex; var inner = ire.InnerException; inner.Data["ThisInfo"] = ire.ThisInfo; inner.Data["StackTrace"] = ire.StackTrace; inner.Data["LocalInfo"] = ire.LocalInfo; ex = inner; } else { var debugger = AppDomain.DebugService; if (method.HasThis) ex.Data["ThisInfo"] = debugger.GetThisInfo(this); else ex.Data["ThisInfo"] = ""; ex.Data["StackTrace"] = debugger.GetStackTrance(this); ex.Data["LocalInfo"] = debugger.GetLocalVariableInfo(this); } //Clear call stack while (stack.Frames.Peek().BasePointer != frame.BasePointer) { var f = stack.Frames.Peek(); esp = stack.PopFrame(ref f, esp); if (f.Method.ReturnType != AppDomain.VoidType) { Free(esp - 1); esp--; } } esp = PushObject(esp, mStack, ex); unhandledException = false; ip = ptr + eh.HandlerStart; continue; } } if (unhandledException) { throw ex; } unhandledException = true; returned = true; #if DEBUG if (!AppDomain.DebugService.Break(this, ex)) #endif { var newEx = new ILRuntimeException(ex.Message, this, method, ex); throw newEx; } } } } #if UNITY_EDITOR if (System.Threading.Thread.CurrentThread.ManagedThreadId == AppDomain.UnityMainThreadID) #if UNITY_5_5_OR_NEWER UnityEngine.Profiling.Profiler.EndSample(); #else UnityEngine.Profiler.EndSample(); #endif #endif //ClearStack return stack.PopFrame(ref frame, esp); } void DumpStack(StackObject* esp) { AppDomain.DebugService.DumpStack(esp, stack); } void CloneStackValueType(StackObject* src, StackObject* dst, IList mStack) { StackObject* descriptor = *(StackObject**)&src->Value; stack.AllocValueType(dst, AppDomain.GetType(descriptor->Value)); StackObject* dstDescriptor = *(StackObject**)&dst->Value; int cnt = descriptor->ValueLow; for(int i = 0; i < cnt; i++) { StackObject* val = Minus(descriptor, i + 1); CopyToValueTypeField(dstDescriptor, i, val, mStack); } } void CopyStackValueType(StackObject* src, StackObject* dst, IList mStack) { StackObject* descriptor = *(StackObject**)&src->Value; StackObject* dstDescriptor = *(StackObject**)&dst->Value; if (descriptor->Value != dstDescriptor->Value) throw new InvalidCastException(); int cnt = descriptor->ValueLow; for(int i = 0; i < cnt; i++) { StackObject* srcVal = Minus(descriptor, i + 1); StackObject* dstVal = Minus(dstDescriptor, i + 1); if (srcVal->ObjectType != dstVal->ObjectType) throw new NotSupportedException(); switch (dstVal->ObjectType) { case ObjectTypes.Object: case ObjectTypes.ArrayReference: case ObjectTypes.FieldReference: mStack[dstVal->Value] = mStack[srcVal->Value]; break; case ObjectTypes.ValueTypeObjectReference: CopyStackValueType(srcVal, dstVal, mStack); break; default: *dstVal = *srcVal; break; } } } void CopyToValueTypeField(StackObject* obj, int idx, StackObject* val, IList mStack) { StackObject* dst = Minus(obj, idx + 1); switch (val->ObjectType) { case ObjectTypes.Null: { mStack[dst->Value] = null; } break; case ObjectTypes.Object: case ObjectTypes.FieldReference: case ObjectTypes.ArrayReference: { if (dst->ObjectType == ObjectTypes.ValueTypeObjectReference) { var ins = mStack[val->Value]; dst = *(StackObject**)&dst->Value; if (ins is ILTypeInstance) { ((ILTypeInstance)ins).CopyValueTypeToStack(dst, mStack); } else { var vb = ((CLRType)domain.GetType(dst->Value)).ValueTypeBinder; vb.CopyValueTypeToStack(ins, dst, mStack); } } else { mStack[dst->Value] = CheckAndCloneValueType(mStack[val->Value], domain); } } break; case ObjectTypes.ValueTypeObjectReference: { if (dst->ObjectType == ObjectTypes.ValueTypeObjectReference) { CopyStackValueType(val, dst, mStack); } else throw new NotImplementedException(); } break; default: *dst = *val; break; } } void StLocSub(StackObject* esp, StackObject* v, StackObject* bp, int idx, IList mStack) { switch (esp->ObjectType) { case ObjectTypes.Null: v->ObjectType = ObjectTypes.Object; v->Value = idx; mStack[idx] = null; break; case ObjectTypes.Object: case ObjectTypes.FieldReference: case ObjectTypes.ArrayReference: if (v->ObjectType == ObjectTypes.ValueTypeObjectReference) { var obj = mStack[esp->Value]; if (obj is ILTypeInstance) { var dst = *(StackObject**)&v->Value; ((ILTypeInstance)obj).CopyValueTypeToStack(dst, mStack); } else { var dst = *(StackObject**)&v->Value; var ct = domain.GetType(dst->Value) as CLRType; var binder = ct.ValueTypeBinder; binder.CopyValueTypeToStack(obj, dst, mStack); } } else { *v = *esp; mStack[idx] = CheckAndCloneValueType(mStack[v->Value], domain); v->Value = idx; } Free(esp); break; case ObjectTypes.ValueTypeObjectReference: if (v->ObjectType == ObjectTypes.ValueTypeObjectReference) { CopyStackValueType(esp, v, mStack); } else throw new NotImplementedException(); FreeStackValueType(esp); break; default: *v = *esp; mStack[idx] = null; break; } } object RetriveObject(StackObject* esp, IList mStack) { StackObject* objRef = GetObjectAndResolveReference(esp); if (objRef->ObjectType == ObjectTypes.Null) return null; object obj = null; switch (objRef->ObjectType) { case ObjectTypes.Object: obj = mStack[objRef->Value]; break; case ObjectTypes.FieldReference: { obj = mStack[objRef->Value]; int idx = objRef->ValueLow; if (obj is ILTypeInstance) { obj = ((ILTypeInstance)obj)[idx]; } else { var t = AppDomain.GetType(obj.GetType()); obj = ((CLRType) t).GetFieldValue(idx, obj); } } break; case ObjectTypes.ArrayReference: { Array arr = mStack[objRef->Value] as Array; int idx = objRef->ValueLow; obj = arr.GetValue(idx); obj = obj.GetType().CheckCLRTypes(obj); } break; case ObjectTypes.StaticFieldReference: { var t = AppDomain.GetType(objRef->Value); int idx = objRef->ValueLow; if (t is ILType) { obj = ((ILType)t).StaticInstance[idx]; } else { obj = ((CLRType)t).GetFieldValue(idx, null); } } break; default: throw new NotImplementedException(); } return obj; } void ArraySetValue(Array arr, object obj, int idx) { if (obj == null) arr.SetValue(null, idx); else arr.SetValue(arr.GetType().GetElementType().CheckCLRTypes(obj), idx); } void StoreIntValueToArray(Array arr, StackObject* val, StackObject* idx) { { int[] tmp = arr as int[]; if (tmp != null) { tmp[idx->Value] = val->Value; return; } } { short[] tmp = arr as short[]; if (tmp != null) { tmp[idx->Value] = (short)val->Value; return; } } { byte[] tmp = arr as byte[]; if (tmp != null) { tmp[idx->Value] = (byte)val->Value; return; } } { bool[] tmp = arr as bool[]; if (tmp != null) { tmp[idx->Value] = val->Value == 1; return; } } { uint[] tmp = arr as uint[]; if (tmp != null) { tmp[idx->Value] = (uint)val->Value; return; } } { ushort[] tmp = arr as ushort[]; if (tmp != null) { tmp[idx->Value] = (ushort)val->Value; return; } } { char[] tmp = arr as char[]; if (tmp != null) { tmp[idx->Value] = (char)val->Value; return; } } { sbyte[] tmp = arr as sbyte[]; if (tmp != null) { tmp[idx->Value] = (sbyte)val->Value; return; } } throw new NotImplementedException(); } ExceptionHandler GetCorrespondingExceptionHandler(ILMethod method, object obj, int addr, ExceptionHandlerType type, bool explicitMatch) { ExceptionHandler res = null; int distance = int.MaxValue; Exception ex = obj is ILRuntimeException ? ((ILRuntimeException)obj).InnerException : obj as Exception; foreach (var i in method.ExceptionHandler) { if (i.HandlerType == type) { if (addr >= i.TryStart && addr <= i.TryEnd) { if (CheckExceptionType(i.CatchType, ex, explicitMatch)) { int d = addr - i.TryStart; if (d < distance) { distance = d; res = i; } } } } } return res; } void LoadFromFieldReference(object obj, int idx, StackObject* dst, IList mStack) { if (obj is ILTypeInstance) { ((ILTypeInstance)obj).PushToStack(idx, dst, AppDomain, mStack); } else { CLRType t = AppDomain.GetType(obj.GetType()) as CLRType; ILIntepreter.PushObject(dst, mStack, t.GetFieldValue(idx, obj)); } } void StoreValueToFieldReference(object obj, int idx, StackObject* val, IList mStack) { if (obj is ILTypeInstance) { ((ILTypeInstance)obj).AssignFromStack(idx, val, AppDomain, mStack); } else { CLRType t = AppDomain.GetType(obj.GetType()) as CLRType; var v = obj.GetType().CheckCLRTypes(CheckAndCloneValueType(StackObject.ToObject(val, AppDomain, mStack), AppDomain)); t.SetFieldValue(idx, ref obj, v); } } void LoadFromArrayReference(object obj, int idx, StackObject* objRef, IType t, IList mStack) { var nT = t.TypeForCLR; LoadFromArrayReference(obj, idx, objRef, nT, mStack); } void LoadFromArrayReference(object obj, int idx, StackObject* objRef, Type nT, IList mStack) { if (nT.IsPrimitive) { if (nT == typeof(int)) { int[] arr = obj as int[]; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = arr[idx]; objRef->ValueLow = 0; } else if (nT == typeof(short)) { short[] arr = obj as short[]; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = arr[idx]; objRef->ValueLow = 0; } else if (nT == typeof(long)) { long[] arr = obj as long[]; objRef->ObjectType = ObjectTypes.Long; *(long*)&objRef->Value = arr[idx]; objRef->ValueLow = 0; } else if (nT == typeof(float)) { float[] arr = obj as float[]; objRef->ObjectType = ObjectTypes.Float; *(float*)&objRef->Value = arr[idx]; objRef->ValueLow = 0; } else if (nT == typeof(double)) { double[] arr = obj as double[]; objRef->ObjectType = ObjectTypes.Double; *(double*)&objRef->Value = arr[idx]; objRef->ValueLow = 0; } else if (nT == typeof(byte)) { byte[] arr = obj as byte[]; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = arr[idx]; objRef->ValueLow = 0; } else if (nT == typeof(char)) { char[] arr = obj as char[]; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = arr[idx]; objRef->ValueLow = 0; } else if (nT == typeof(uint)) { uint[] arr = obj as uint[]; objRef->ObjectType = ObjectTypes.Integer; *(uint*)&objRef->Value = arr[idx]; objRef->ValueLow = 0; } else if (nT == typeof(sbyte)) { sbyte[] arr = obj as sbyte[]; objRef->ObjectType = ObjectTypes.Integer; objRef->Value = arr[idx]; objRef->ValueLow = 0; } else throw new NotImplementedException(); } else { Array arr = obj as Array; objRef->ObjectType = ObjectTypes.Object; objRef->Value = mStack.Count; mStack.Add(arr.GetValue(idx)); objRef->ValueLow = 0; } } void StoreValueToArrayReference(StackObject* objRef, StackObject* val, IType t, IList mStack) { var nT = t.TypeForCLR; StoreValueToArrayReference(objRef, val, nT, mStack); } void StoreValueToArrayReference(StackObject* objRef, StackObject* val, Type nT, IList mStack) { if (nT.IsPrimitive) { if (nT == typeof(int)) { int[] arr = mStack[objRef->Value] as int[]; arr[objRef->ValueLow] = val->Value; } else if (nT == typeof(short)) { short[] arr = mStack[objRef->Value] as short[]; arr[objRef->ValueLow] = (short)val->Value; } else if (nT == typeof(long)) { long[] arr = mStack[objRef->Value] as long[]; arr[objRef->ValueLow] = *(long*)&val->Value; } else if (nT == typeof(float)) { float[] arr = mStack[objRef->Value] as float[]; arr[objRef->ValueLow] = *(float*)&val->Value; } else if (nT == typeof(double)) { double[] arr = mStack[objRef->Value] as double[]; arr[objRef->ValueLow] = *(double*)&val->Value; } else if (nT == typeof(byte)) { byte[] arr = mStack[objRef->Value] as byte[]; arr[objRef->ValueLow] = (byte)val->Value; } else if (nT == typeof(char)) { char[] arr = mStack[objRef->Value] as char[]; arr[objRef->ValueLow] = (char)val->Value; } else if (nT == typeof(uint)) { uint[] arr = mStack[objRef->Value] as uint[]; arr[objRef->ValueLow] = (uint)val->Value; } else if (nT == typeof(sbyte)) { sbyte[] arr = mStack[objRef->Value] as sbyte[]; arr[objRef->ValueLow] = (sbyte)val->Value; } else throw new NotImplementedException(); } else { Array arr = mStack[objRef->Value] as Array; arr.SetValue(mStack[val->Value], objRef->ValueLow); } } bool CheckExceptionType(IType catchType, object exception, bool explicitMatch) { if (catchType is CLRType) { if (explicitMatch) return exception.GetType() == catchType.TypeForCLR; else return catchType.TypeForCLR.IsAssignableFrom(exception.GetType()); } else throw new NotImplementedException(); } public static StackObject* GetObjectAndResolveReference(StackObject* esp) { if (esp->ObjectType == ObjectTypes.StackObjectReference) { return *(StackObject**)&esp->Value; } else return esp; } StackObject* PushParameters(IMethod method, StackObject* esp, object[] p) { IList mStack = stack.ManagedStack; var plist = method.Parameters; int pCnt = plist != null ? plist.Count : 0; int pCnt2 = p != null ? p.Length : 0; if (pCnt != pCnt2) throw new ArgumentOutOfRangeException("Parameter mismatch"); if (pCnt2 > 0) { for (int i = 0; i < p.Length; i++) { bool isBox = false; if (plist != null && i < plist.Count) isBox = plist[i] == AppDomain.ObjectType; object obj = p[i]; if (obj is CrossBindingAdaptorType) obj = ((CrossBindingAdaptorType)obj).ILInstance; esp = ILIntepreter.PushObject(esp, mStack, obj, isBox); } } return esp; } public void CopyToStack(StackObject* dst, StackObject* src, IList mStack) { *dst = *src; if (dst->ObjectType >= ObjectTypes.Object) { dst->Value = mStack.Count; var obj = mStack[src->Value]; mStack.Add(obj); } } internal static object CheckAndCloneValueType(object obj, Enviorment.AppDomain domain) { if (obj != null) { if (obj is ILTypeInstance) { ILTypeInstance ins = obj as ILTypeInstance; if (ins.IsValueType) { return ins.Clone(); } } else { var type = obj.GetType(); var typeFlags = type.GetTypeFlags(); var isPrimitive = (typeFlags & CLR.Utils.Extensions.TypeFlags.IsPrimitive) != 0; var isValueType = (typeFlags & CLR.Utils.Extensions.TypeFlags.IsValueType) != 0; if (!isPrimitive && isValueType) { var t = domain.GetType(type); return ((CLRType)t).PerformMemberwiseClone(obj); } } } return obj; } public static StackObject* PushOne(StackObject* esp) { esp->ObjectType = ObjectTypes.Integer; esp->Value = 1; return esp + 1; } public static StackObject* PushZero(StackObject* esp) { esp->ObjectType = ObjectTypes.Integer; esp->Value = 0; return esp + 1; } public static StackObject* PushNull(StackObject* esp) { esp->ObjectType = ObjectTypes.Null; esp->Value = -1; esp->ValueLow = 0; return esp + 1; } public static void UnboxObject(StackObject* esp, object obj) { if (obj is int) { esp->ObjectType = ObjectTypes.Integer; esp->Value = (int)obj; } else if (obj is bool) { esp->ObjectType = ObjectTypes.Integer; esp->Value = (bool)(obj) ? 1 : 0; } else if (obj is short) { esp->ObjectType = ObjectTypes.Integer; esp->Value = (short)obj; } else if (obj is long) { esp->ObjectType = ObjectTypes.Long; *(long*)(&esp->Value) = (long)obj; } else if (obj is float) { esp->ObjectType = ObjectTypes.Float; *(float*)(&esp->Value) = (float)obj; } else if (obj is byte) { esp->ObjectType = ObjectTypes.Integer; esp->Value = (byte)obj; } else if (obj is uint) { esp->ObjectType = ObjectTypes.Integer; esp->Value = (int)(uint)obj; } else if (obj is ushort) { esp->ObjectType = ObjectTypes.Integer; esp->Value = (int)(ushort)obj; } else if (obj is char) { esp->ObjectType = ObjectTypes.Integer; esp->Value = (int)(char)obj; } else if (obj is double) { esp->ObjectType = ObjectTypes.Double; *(double*)(&esp->Value) = (double)obj; } else if (obj is ulong) { esp->ObjectType = ObjectTypes.Long; *(ulong*)(&esp->Value) = (ulong)obj; } else if (obj is sbyte) { esp->ObjectType = ObjectTypes.Integer; esp->Value = (sbyte)obj; } else throw new NotImplementedException(); } public static StackObject* PushObject(StackObject* esp, IList mStack, object obj, bool isBox = false) { if (obj != null) { if (!isBox) { var typeFlags = obj.GetType().GetTypeFlags(); if ((typeFlags & CLR.Utils.Extensions.TypeFlags.IsPrimitive) != 0) { UnboxObject(esp, obj); } else if ((typeFlags & CLR.Utils.Extensions.TypeFlags.IsEnum) != 0) { esp->ObjectType = ObjectTypes.Integer; esp->Value = Convert.ToInt32(obj); } else { esp->ObjectType = ObjectTypes.Object; esp->Value = mStack.Count; mStack.Add(obj); } } else { esp->ObjectType = ObjectTypes.Object; esp->Value = mStack.Count; mStack.Add(obj); } } else { return PushNull(esp); } return esp + 1; } //Don't ask me why add this funky method for this, otherwise Unity won't calculate the right value public static StackObject* Add(StackObject* a, int b) { return (StackObject*)((long)a + sizeof(StackObject) * b); } public static StackObject* Minus(StackObject* a, int b) { return (StackObject*)((long)a - sizeof(StackObject) * b); } public void Free(StackObject* esp) { if (esp->ObjectType >= ObjectTypes.Object) { if (esp->Value == stack.ManagedStack.Count - 1) stack.ManagedStack.RemoveAt(esp->Value); } #if DEBUG esp->ObjectType = ObjectTypes.Null; esp->Value = -1; esp->ValueLow = 0; #endif } public void FreeStackValueType(StackObject* esp) { if (esp->ObjectType == ObjectTypes.ValueTypeObjectReference) { var addr = *(StackObject**)&esp->Value; if (addr <= ValueTypeBasePointer)//Only Stack allocation after base pointer should be freed, local variable are freed automatically stack.FreeValueTypeObject(esp); } } public void AllocValueType(StackObject* ptr, IType type) { stack.AllocValueType(ptr, type); } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Intepreter/ILRuntimeException.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.Runtime.Stack; namespace ILRuntime.Runtime.Intepreter { public class ILRuntimeException : Exception { string stackTrace; string thisInfo, localInfo; internal ILRuntimeException(string message, ILIntepreter intepreter, CLR.Method.ILMethod method, Exception innerException = null) : base(message, innerException) { var ds = intepreter.AppDomain.DebugService; if (innerException is ILRuntimeException) { ILRuntimeException e = innerException as ILRuntimeException; stackTrace = e.stackTrace; thisInfo = e.thisInfo; localInfo = e.localInfo; } else { stackTrace = ds.GetStackTrance(intepreter); if (method.HasThis) thisInfo = ds.GetThisInfo(intepreter); else thisInfo = ""; localInfo = ds.GetLocalVariableInfo(intepreter); } } public override string StackTrace { get { return stackTrace; } } public string ThisInfo { get { return thisInfo; } } public string LocalInfo { get { return localInfo; } } public override string ToString() { StringBuilder message = new StringBuilder(); message.AppendLine(Message); if (!string.IsNullOrEmpty(ThisInfo)) { message.AppendLine("this:"); message.AppendLine(ThisInfo); } message.AppendLine("Local Variables:"); message.AppendLine(LocalInfo); message.AppendLine(StackTrace); if (InnerException != null) message.AppendLine(InnerException.ToString()); return message.ToString(); } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Intepreter/ILTypeInstance.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.Utils; using ILRuntime.CLR.Method; using ILRuntime.CLR.TypeSystem; using ILRuntime.Runtime.Stack; namespace ILRuntime.Runtime.Intepreter { public class ILTypeStaticInstance : ILTypeInstance { public unsafe ILTypeStaticInstance(ILType type) { this.type = type; fields = new StackObject[type.StaticFieldTypes.Length]; managedObjs = new List(fields.Length); for (int i = 0; i < fields.Length; i++) { var ft = type.StaticFieldTypes[i]; var t = ft.TypeForCLR; managedObjs.Add(null); StackObject.Initialized(ref fields[i], i, t, ft, managedObjs); } int idx = 0; foreach (var i in type.TypeDefinition.Fields) { if (i.IsStatic) { if (i.InitialValue != null && i.InitialValue.Length > 0) { fields[idx].ObjectType = ObjectTypes.Object; managedObjs[idx] = i.InitialValue; } idx++; } } } } unsafe class ILEnumTypeInstance : ILTypeInstance { public ILEnumTypeInstance(ILType type) { if (!type.IsEnum) throw new NotSupportedException(); this.type = type; fields = new StackObject[1]; } public override string ToString() { var fields = type.TypeDefinition.Fields; long longVal = 0; int intVal = 0; bool isLong = this.fields[0].ObjectType == ObjectTypes.Long; if (isLong) { fixed (StackObject* f = this.fields) longVal = *(long*)&f->Value; } else intVal = this.fields[0].Value; for (int i = 0; i < fields.Count; i++) { var f = fields[i]; if (f.IsStatic) { if (isLong) { long val = f.Constant is long ? (long)f.Constant : (long)(ulong)f.Constant; if (val == longVal) return f.Name; } else { if (f.Constant is int) { if ((int)f.Constant == intVal) return f.Name; } else if (f.Constant is short) { if ((short)f.Constant == intVal) return f.Name; } else if (f.Constant is byte) { if ((byte)f.Constant == intVal) return f.Name; } else throw new NotImplementedException(); } } } return isLong ? longVal.ToString() : intVal.ToString(); } } public class ILTypeInstance { protected ILType type; protected StackObject[] fields; protected IList managedObjs; object clrInstance; Dictionary delegates; public ILType Type { get { return type; } } public StackObject[] Fields { get { return fields; } } public virtual bool IsValueType { get { return type.IsValueType && !Boxed; } } /// /// 是否已装箱 /// public bool Boxed { get; set; } public IList ManagedObjects { get { return managedObjs; } } public object CLRInstance { get { return clrInstance; } set { clrInstance = value; } } protected ILTypeInstance() { } public ILTypeInstance(ILType type, bool initializeCLRInstance = true) { this.type = type; fields = new StackObject[type.TotalFieldCount]; managedObjs = new List(fields.Length); for (int i = 0; i < fields.Length; i++) { managedObjs.Add(null); } InitializeFields(type); if (initializeCLRInstance) { if (type.FirstCLRBaseType is Enviorment.CrossBindingAdaptor) { clrInstance = ((Enviorment.CrossBindingAdaptor)type.FirstCLRBaseType).CreateCLRInstance(type.AppDomain, this); } else { clrInstance = this; } if(type.FirstCLRInterface is Enviorment.CrossBindingAdaptor) { if (clrInstance != this)//Only one CLRInstance is allowed atm, so implementing multiple interfaces is not supported { throw new NotSupportedException("Inheriting and implementing interface at the same time is not supported yet"); } clrInstance = ((Enviorment.CrossBindingAdaptor)type.FirstCLRInterface).CreateCLRInstance(type.AppDomain, this); } } else clrInstance = this; } public unsafe object this[int index] { get { if (index < fields.Length && index >= 0) { fixed (StackObject* ptr = fields) { StackObject* esp = &ptr[index]; return StackObject.ToObject(esp, null, managedObjs); } } else { if (Type.FirstCLRBaseType != null && Type.FirstCLRBaseType is Enviorment.CrossBindingAdaptor) { CLRType clrType = type.AppDomain.GetType(((Enviorment.CrossBindingAdaptor)Type.FirstCLRBaseType).BaseCLRType) as CLRType; return clrType.GetFieldValue(index, clrInstance); } else throw new TypeLoadException(); } } set { value = ILIntepreter.CheckAndCloneValueType(value, type.AppDomain); if (index < fields.Length && index >= 0) { fixed (StackObject* ptr = fields) { StackObject* esp = &ptr[index]; if (value != null) { if (value.GetType().IsPrimitive) { ILIntepreter.UnboxObject(esp, value); } else { esp->ObjectType = ObjectTypes.Object; esp->Value = index; managedObjs[index] = value; } } else *esp = StackObject.Null; } } else { if (Type.FirstCLRBaseType != null && Type.FirstCLRBaseType is Enviorment.CrossBindingAdaptor) { CLRType clrType = type.AppDomain.GetType(((Enviorment.CrossBindingAdaptor)Type.FirstCLRBaseType).BaseCLRType) as CLRType; clrType.SetFieldValue(index, ref clrInstance, value); } else throw new TypeLoadException(); } } } void InitializeFields(ILType type) { for (int i = 0; i < type.FieldTypes.Length; i++) { var ft = type.FieldTypes[i]; StackObject.Initialized(ref fields[type.FieldStartIndex + i], type.FieldStartIndex + i, ft.TypeForCLR, ft, managedObjs); } if (type.BaseType != null && type.BaseType is ILType) InitializeFields((ILType)type.BaseType); } internal unsafe void PushFieldAddress(int fieldIdx, StackObject* esp, IList managedStack) { esp->ObjectType = ObjectTypes.FieldReference; esp->Value = managedStack.Count; managedStack.Add(this); esp->ValueLow = fieldIdx; } internal unsafe void PushToStack(int fieldIdx, StackObject* esp, Enviorment.AppDomain appdomain, IList managedStack) { if (fieldIdx < fields.Length && fieldIdx >= 0) PushToStackSub(ref fields[fieldIdx], fieldIdx, esp, managedStack); else { if (Type.FirstCLRBaseType != null && Type.FirstCLRBaseType is Enviorment.CrossBindingAdaptor) { CLRType clrType = appdomain.GetType(((Enviorment.CrossBindingAdaptor)Type.FirstCLRBaseType).BaseCLRType) as CLRType; ILIntepreter.PushObject(esp, managedStack, clrType.GetFieldValue(fieldIdx, clrInstance)); } else throw new TypeLoadException(); } } unsafe void PushToStackSub(ref StackObject field, int fieldIdx, StackObject* esp, IList managedStack) { *esp = field; if (field.ObjectType >= ObjectTypes.Object) { esp->Value = managedStack.Count; managedStack.Add(managedObjs[fieldIdx]); } } internal unsafe void CopyValueTypeToStack(StackObject* ptr, IList mStack) { ptr->ObjectType = ObjectTypes.ValueTypeDescriptor; ptr->Value = type.GetHashCode(); ptr->ValueLow = type.TotalFieldCount; for(int i = 0; i < fields.Length; i++) { var val = ILIntepreter.Minus(ptr, i + 1); switch (val->ObjectType) { case ObjectTypes.Object: case ObjectTypes.FieldReference: case ObjectTypes.ArrayReference: mStack[val->Value] = managedObjs[i]; val->ValueLow = fields[i].ValueLow; break; case ObjectTypes.ValueTypeObjectReference: { var obj = managedObjs[i]; var dst = *(StackObject**)&val->Value; var vt = type.AppDomain.GetType(dst->Value); if (vt is ILType) { ((ILTypeInstance)obj).CopyValueTypeToStack(dst, mStack); } else { ((CLRType)vt).ValueTypeBinder.CopyValueTypeToStack(obj, dst, mStack); } } break; default: *val = fields[i]; break; } } } internal void Clear() { InitializeFields(type); } internal unsafe void AssignFromStack(int fieldIdx, StackObject* esp, Enviorment.AppDomain appdomain, IList managedStack) { if (fieldIdx < fields.Length && fieldIdx >= 0) AssignFromStackSub(ref fields[fieldIdx], fieldIdx, esp, managedStack); else { if (Type.FirstCLRBaseType != null && Type.FirstCLRBaseType is Enviorment.CrossBindingAdaptor) { CLRType clrType = appdomain.GetType(((Enviorment.CrossBindingAdaptor)Type.FirstCLRBaseType).BaseCLRType) as CLRType; var field = clrType.GetField(fieldIdx); clrType.SetFieldValue(fieldIdx, ref clrInstance, field.FieldType.CheckCLRTypes(ILIntepreter.CheckAndCloneValueType(StackObject.ToObject(esp, appdomain, managedStack), appdomain))); } else throw new TypeLoadException(); } } internal unsafe void AssignFromStack(StackObject* esp, Enviorment.AppDomain appdomain, IList managedStack) { StackObject* val = *(StackObject**)&esp->Value; int cnt = val->ValueLow; for (int i = 0; i < cnt; i++) { var addr = ILIntepreter.Minus(val, i + 1); AssignFromStack(i, addr, type.AppDomain, managedStack); } } unsafe void AssignFromStackSub(ref StackObject field, int fieldIdx, StackObject* esp, IList managedStack) { esp = ILIntepreter.GetObjectAndResolveReference(esp); field = *esp; switch (field.ObjectType) { case ObjectTypes.Object: case ObjectTypes.ArrayReference: case ObjectTypes.FieldReference: field.Value = fieldIdx; managedObjs[fieldIdx] = ILIntepreter.CheckAndCloneValueType(managedStack[esp->Value], Type.AppDomain); break; case ObjectTypes.ValueTypeObjectReference: { var domain = type.AppDomain; field.ObjectType = ObjectTypes.Object; field.Value = fieldIdx; var dst = *(StackObject**)&esp->Value; var vt = domain.GetType(dst->Value); if(vt is ILType) { var ins = managedObjs[fieldIdx]; if (ins == null) throw new NullReferenceException(); ILTypeInstance child = (ILTypeInstance)ins; child.AssignFromStack(esp, domain, managedStack); } else { managedObjs[fieldIdx] = ((CLRType)vt).ValueTypeBinder.ToObject(dst, managedStack); } } break; default: if (managedObjs != null) managedObjs[fieldIdx] = null; break; } } public override string ToString() { IMethod m = type.AppDomain.ObjectType.GetMethod("ToString", 0); m = type.GetVirtualMethod(m); if (m != null) { if (m is ILMethod) { var res = type.AppDomain.Invoke(m, this, null); return res.ToString(); } else return clrInstance.ToString(); } else return type.FullName; } public bool CanAssignTo(IType type) { return this.type.CanAssignTo(type); } public ILTypeInstance Clone() { ILTypeInstance ins = new ILTypeInstance(type); for (int i = 0; i < fields.Length; i++) { ins.fields[i] = fields[i]; ins.managedObjs[i] = managedObjs[i]; } if (type.FirstCLRBaseType is Enviorment.CrossBindingAdaptor) { ins.clrInstance = ((Enviorment.CrossBindingAdaptor)type.FirstCLRBaseType).CreateCLRInstance(type.AppDomain, ins); } else { ins.clrInstance = ins; } return ins; } internal IDelegateAdapter GetDelegateAdapter(ILMethod method) { if (delegates == null) delegates = new Dictionary(); IDelegateAdapter res; if (delegates.TryGetValue(method, out res)) return res; return null; } internal void SetDelegateAdapter(ILMethod method, IDelegateAdapter adapter) { if (!delegates.ContainsKey(method)) delegates[method] = adapter; else throw new NotSupportedException(); } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Intepreter/OpCodes/OpCode.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.Method; namespace ILRuntime.Runtime.Intepreter.OpCodes { /// /// IL指令 /// struct OpCode { /// /// 当前指令 /// public OpCodeEnum Code; /// /// Int32 操作数 /// public int TokenInteger; /// /// Int64 操作数 /// public long TokenLong; } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Intepreter/OpCodes/OpCodeEnum.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ILRuntime.Runtime.Intepreter.OpCodes { enum OpCodeEnum { /// /// 如果修补操作码,则填充空间。尽管可能消耗处理周期,但未执行任何有意义的操作。 /// Nop, /// /// 向公共语言结构 (CLI) 发出信号以通知调试器已撞上了一个断点。 /// Break, /// /// 将索引为 0 的参数加载到计算堆栈上。 /// Ldarg_0, /// /// 将索引为 1 的参数加载到计算堆栈上。 /// Ldarg_1, /// /// 将索引为 2 的参数加载到计算堆栈上。 /// Ldarg_2, /// /// 将索引为 3 的参数加载到计算堆栈上。 /// Ldarg_3, /// /// 将索引 0 处的局部变量加载到计算堆栈上。 /// Ldloc_0, /// /// 将索引 1 处的局部变量加载到计算堆栈上。 /// Ldloc_1, /// /// 将索引 2 处的局部变量加载到计算堆栈上。 /// Ldloc_2, /// /// 将索引 3 处的局部变量加载到计算堆栈上。 /// Ldloc_3, /// /// 从计算堆栈的顶部弹出当前值并将其存储到索引 0 处的局部变量列表中。 /// Stloc_0, /// /// 从计算堆栈的顶部弹出当前值并将其存储到索引 1 处的局部变量列表中。 /// Stloc_1, /// /// 从计算堆栈的顶部弹出当前值并将其存储到索引 2 处的局部变量列表中。 /// Stloc_2, /// /// 从计算堆栈的顶部弹出当前值并将其存储到索引 3 处的局部变量列表中。 /// Stloc_3, /// /// 将参数(由指定的短格式索引引用)加载到计算堆栈上。 /// Ldarg_S, /// /// 以短格式将参数地址加载到计算堆栈上。 /// Ldarga_S, /// /// 将位于计算堆栈顶部的值存储在参数槽中的指定索引处(短格式)。 /// Starg_S, /// /// 将特定索引处的局部变量加载到计算堆栈上(短格式)。 /// Ldloc_S, /// /// 将位于特定索引处的局部变量的地址加载到计算堆栈上(短格式)。 /// Ldloca_S, /// /// 从计算堆栈的顶部弹出当前值并将其存储在局部变量列表中的 index 处(短格式)。 /// Stloc_S, /// /// 将空引用(O 类型)推送到计算堆栈上。 /// Ldnull, /// /// 将整数值 -1 作为 int32 推送到计算堆栈上。 /// Ldc_I4_M1, /// /// 将整数值 0 作为 int32 推送到计算堆栈上。 /// Ldc_I4_0, /// /// 将整数值 1 作为 int32 推送到计算堆栈上。 /// Ldc_I4_1, /// /// 将整数值 2 作为 int32 推送到计算堆栈上。 /// Ldc_I4_2, /// /// 将整数值 3 作为 int32 推送到计算堆栈上。 /// Ldc_I4_3, /// /// 将整数值 4 作为 int32 推送到计算堆栈上。 /// Ldc_I4_4, /// /// 将整数值 5 作为 int32 推送到计算堆栈上。 /// Ldc_I4_5, /// /// 将整数值 6 作为 int32 推送到计算堆栈上。 /// Ldc_I4_6, /// /// 将整数值 7 作为 int32 推送到计算堆栈上。 /// Ldc_I4_7, /// /// 将整数值 8 作为 int32 推送到计算堆栈上。 /// Ldc_I4_8, /// /// 将提供的 int8 值作为 int32 推送到计算堆栈上(短格式)。 /// Ldc_I4_S, /// /// 将所提供的 int32 类型的值作为 int32 推送到计算堆栈上。 /// Ldc_I4, /// /// 将所提供的 int64 类型的值作为 int64 推送到计算堆栈上。 /// Ldc_I8, /// /// 将所提供的 float32 类型的值作为 F (float) 类型推送到计算堆栈上。 /// Ldc_R4, /// /// 将所提供的 float64 类型的值作为 F (float) 类型推送到计算堆栈上。 /// Ldc_R8, /// /// 复制计算堆栈上当前最顶端的值,然后将副本推送到计算堆栈上。 /// Dup, /// /// 移除当前位于计算堆栈顶部的值。 /// Pop, /// /// 退出当前方法并跳至指定方法。 /// Jmp, /// /// 调用由传递的方法说明符指示的方法。 /// Call, /// /// 通过调用约定描述的参数调用在计算堆栈上指示的方法(作为指向入口点的指针)。 /// Calli, /// /// 从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。 /// Ret, /// /// 无条件地将控制转移到目标指令(短格式)。 /// Br_S, /// /// 如果 value 为 false、空引用或零,则将控制转移到目标指令。 /// Brfalse_S, /// /// 如果 value 为 true、非空或非零,则将控制转移到目标指令(短格式)。 /// Brtrue_S, /// /// 如果两个值相等,则将控制转移到目标指令(短格式)。 /// Beq_S, /// /// 如果第一个值大于或等于第二个值,则将控制转移到目标指令(短格式)。 /// Bge_S, /// /// 如果第一个值大于第二个值,则将控制转移到目标指令(短格式)。 /// Bgt_S, /// /// 如果第一个值小于或等于第二个值,则将控制转移到目标指令(短格式)。 /// Ble_S, /// /// 如果第一个值小于第二个值,则将控制转移到目标指令(短格式)。 /// Blt_S, /// /// 当两个无符号整数值或不可排序的浮点型值不相等时,将控制转移到目标指令(短格式)。 /// Bne_Un_S, /// /// 当比较无符号整数值或不可排序的浮点型值时,如果第一个值大于第二个值,则将控制转移到目标指令(短格式)。 /// Bge_Un_S, /// /// 当比较无符号整数值或不可排序的浮点型值时,如果第一个值大于第二个值,则将控制转移到目标指令(短格式)。 /// Bgt_Un_S, /// /// 当比较无符号整数值或不可排序的浮点值时,如果第一个值小于或等于第二个值,则将控制权转移到目标指令(短格式)。 /// Ble_Un_S, /// /// 当比较无符号整数值或不可排序的浮点型值时,如果第一个值小于第二个值,则将控制转移到目标指令(短格式)。 /// Blt_Un_S, /// /// 无条件地将控制转移到目标指令。 /// Br, /// /// 如果 value 为 false、空引用(Visual Basic 中的 Nothing)或零,则将控制转移到目标指令。 /// Brfalse, /// /// 如果 value 为 true、非空或非零,则将控制转移到目标指令。 /// Brtrue, /// /// 如果两个值相等,则将控制转移到目标指令。 /// Beq, /// /// 如果第一个值大于或等于第二个值,则将控制转移到目标指令。 /// Bge, /// /// 如果第一个值大于第二个值,则将控制转移到目标指令。 /// Bgt, /// /// 如果第一个值小于或等于第二个值,则将控制转移到目标指令。 /// Ble, /// /// 如果第一个值小于第二个值,则将控制转移到目标指令。 /// Blt, /// /// 当两个无符号整数值或不可排序的浮点型值不相等时,将控制转移到目标指令。 /// Bne_Un, /// /// 当比较无符号整数值或不可排序的浮点型值时,如果第一个值大于第二个值,则将控制转移到目标指令。 /// Bge_Un, /// /// 当比较无符号整数值或不可排序的浮点型值时,如果第一个值大于第二个值,则将控制转移到目标指令。 /// Bgt_Un, /// /// 当比较无符号整数值或不可排序的浮点型值时,如果第一个值小于或等于第二个值,则将控制转移到目标指令。 /// Ble_Un, /// /// 当比较无符号整数值或不可排序的浮点型值时,如果第一个值小于第二个值,则将控制转移到目标指令。 /// Blt_Un, /// /// 实现跳转表。 /// Switch, /// /// 将 int8 类型的值作为 int32 间接加载到计算堆栈上。 /// Ldind_I1, /// /// 将 unsigned int8 类型的值作为 int32 间接加载到计算堆栈上。 /// Ldind_U1, /// /// 将 int16 类型的值作为 int32 间接加载到计算堆栈上。 /// Ldind_I2, /// /// 将 unsigned int16 类型的值作为 int32 间接加载到计算堆栈上。 /// Ldind_U2, /// /// 将 int32 类型的值作为 int32 间接加载到计算堆栈上。 /// Ldind_I4, /// /// 将 unsigned int32 类型的值作为 int32 间接加载到计算堆栈上。 /// Ldind_U4, /// /// 将 int64 类型的值作为 int64 间接加载到计算堆栈上。 /// Ldind_I8, /// /// 将 native int 类型的值作为 native int 间接加载到计算堆栈上。 /// Ldind_I, /// /// 将 float32 类型的值作为 F (float) 类型间接加载到计算堆栈上。 /// Ldind_R4, /// /// 将 float64 类型的值作为 F (float) 类型间接加载到计算堆栈上。 /// Ldind_R8, /// /// 将对象引用作为 O(对象引用)类型间接加载到计算堆栈上。 /// Ldind_Ref, /// /// 存储所提供地址处的对象引用值。 /// Stind_Ref, /// /// 在所提供的地址存储 int8 类型的值。 /// Stind_I1, /// /// 在所提供的地址存储 int16 类型的值。 /// Stind_I2, /// /// 在所提供的地址存储 int32 类型的值。 /// Stind_I4, /// /// 在所提供的地址存储 int64 类型的值。 /// Stind_I8, /// /// 在所提供的地址存储 float32 类型的值。 /// Stind_R4, /// /// 在所提供的地址存储 float64 类型的值。 /// Stind_R8, /// /// 将两个值相加并将结果推送到计算堆栈上。 /// Add, /// /// 从其他值中减去一个值并将结果推送到计算堆栈上。 /// Sub, /// /// 将两个值相乘并将结果推送到计算堆栈上。 /// Mul, /// /// 将两个值相除并将结果作为浮点(F 类型)或商(int32 类型)推送到计算堆栈上。 /// Div, /// /// 两个无符号整数值相除并将结果 ( int32 ) 推送到计算堆栈上。 /// Div_Un, /// /// 将两个值相除并将余数推送到计算堆栈上。 /// Rem, /// /// 将两个无符号值相除并将余数推送到计算堆栈上。 /// Rem_Un, /// /// 计算两个值的按位“与”并将结果推送到计算堆栈上。 /// And, /// /// 计算位于堆栈顶部的两个整数值的按位求补并将结果推送到计算堆栈上。 /// Or, /// /// 计算位于计算堆栈顶部的两个值的按位异或,并且将结果推送到计算堆栈上。 /// Xor, /// /// 将整数值左移(用零填充)指定的位数,并将结果推送到计算堆栈上。 /// Shl, /// /// 将整数值右移(保留符号)指定的位数,并将结果推送到计算堆栈上。 /// Shr, /// /// 将无符号整数值右移(用零填充)指定的位数,并将结果推送到计算堆栈上。 /// Shr_Un, /// /// 对一个值执行求反并将结果推送到计算堆栈上。 /// Neg, /// /// 计算堆栈顶部整数值的按位求补并将结果作为相同的类型推送到计算堆栈上。 /// Not, /// /// 将位于计算堆栈顶部的值转换为 int8,然后将其扩展(填充)为 int32。 /// Conv_I1, /// /// 将位于计算堆栈顶部的值转换为 int16,然后将其扩展(填充)为 int32。 /// Conv_I2, /// /// 将位于计算堆栈顶部的值转换为 int32。 /// Conv_I4, /// /// 将位于计算堆栈顶部的值转换为 int64。 /// Conv_I8, /// /// 将位于计算堆栈顶部的值转换为 float32。 /// Conv_R4, /// /// 将位于计算堆栈顶部的值转换为 float64。 /// Conv_R8, /// /// 将位于计算堆栈顶部的值转换为 unsigned int32,然后将其扩展为 int32。 /// Conv_U4, /// /// 将位于计算堆栈顶部的值转换为 unsigned int64,然后将其扩展为 int64。 /// Conv_U8, /// /// 对对象调用后期绑定方法,并且将返回值推送到计算堆栈上。 /// Callvirt, /// /// 将位于对象(&、* 或 native int 类型)地址的值类型复制到目标对象(&、* 或 native int 类型)的地址。 /// Cpobj, /// /// 将地址指向的值类型对象复制到计算堆栈的顶部。 /// Ldobj, /// /// 推送对元数据中存储的字符串的新对象引用。 /// Ldstr, /// /// 创建一个值类型的新对象或新实例,并将对象引用(O 类型)推送到计算堆栈上。 /// Newobj, /// /// 尝试将引用传递的对象转换为指定的类。 /// Castclass, /// /// 测试对象引用(O 类型)是否为特定类的实例。 /// Isinst, /// /// 将位于计算堆栈顶部的无符号整数值转换为 float32。 /// Conv_R_Un, /// /// 将值类型的已装箱的表示形式转换为其未装箱的形式。 /// Unbox, /// /// 引发当前位于计算堆栈上的异常对象。 /// Throw, /// /// 查找对象中其引用当前位于计算堆栈的字段的值。 /// Ldfld, /// /// 查找对象中其引用当前位于计算堆栈的字段的地址。 /// Ldflda, /// /// 用新值替换在对象引用或指针的字段中存储的值。 /// Stfld, /// /// 将静态字段的值推送到计算堆栈上。 /// Ldsfld, /// /// 将静态字段的地址推送到计算堆栈上。 /// Ldsflda, /// /// 用来自计算堆栈的值替换静态字段的值。 /// Stsfld, /// /// 将指定类型的值从计算堆栈复制到所提供的内存地址中。 /// Stobj, /// /// 将位于计算堆栈顶部的无符号值转换为有符号 int8 并将其扩展为 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_I1_Un, /// /// 将位于计算堆栈顶部的无符号值转换为有符号 int16 并将其扩展为 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_I2_Un, /// /// 将位于计算堆栈顶部的无符号值转换为有符号 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_I4_Un, /// /// 将位于计算堆栈顶部的无符号值转换为有符号 int64,并在溢出时引发 OverflowException。 /// Conv_Ovf_I8_Un, /// /// 将位于计算堆栈顶部的无符号值转换为 unsigned int8 并将其扩展为 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_U1_Un, /// /// 将位于计算堆栈顶部的无符号值转换为 unsigned int16 并将其扩展为 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_U2_Un, /// /// 将位于计算堆栈顶部的无符号值转换为 unsigned int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_U4_Un, /// /// 将位于计算堆栈顶部的无符号值转换为 unsigned int64,并在溢出时引发 OverflowException。 /// Conv_Ovf_U8_Un, /// /// 将位于计算堆栈顶部的无符号值转换为有符号 native int,并在溢出时引发 OverflowException。 /// Conv_Ovf_I_Un, /// /// 将位于计算堆栈顶部的无符号值转换为 unsigned native int,并在溢出时引发 OverflowException。 /// Conv_Ovf_U_Un, /// /// 将值类转换为对象引用(O 类型)。 /// Box, /// /// 将对新的从零开始的一维数组(其元素属于特定类型)的对象引用推送到计算堆栈上。 /// Newarr, /// /// 将从零开始的、一维数组的元素的数目推送到计算堆栈上。 /// Ldlen, /// /// 将位于指定数组索引的数组元素的地址作为 & 类型(托管指针)加载到计算堆栈的顶部。 /// Ldelema, /// /// 将位于指定数组索引处的 int8 类型的元素作为 int32 加载到计算堆栈的顶部。 /// Ldelem_I1, /// /// 将位于指定数组索引处的 unsigned int8 类型的元素作为 int32 加载到计算堆栈的顶部。 /// Ldelem_U1, /// /// 将位于指定数组索引处的 int16 类型的元素作为 int32 加载到计算堆栈的顶部。 /// Ldelem_I2, /// /// 将位于指定数组索引处的 unsigned int16 类型的元素作为 int32 加载到计算堆栈的顶部。 /// Ldelem_U2, /// /// 将位于指定数组索引处的 int32 类型的元素作为 int32 加载到计算堆栈的顶部。 /// Ldelem_I4, /// /// 将位于指定数组索引处的 unsigned int32 类型的元素作为 int32 加载到计算堆栈的顶部。 /// Ldelem_U4, /// /// 将位于指定数组索引处的 int64 类型的元素作为 int64 加载到计算堆栈的顶部。 /// Ldelem_I8, /// /// 将位于指定数组索引处的 native int 类型的元素作为 native int 加载到计算堆栈的顶部。 /// Ldelem_I, /// /// 将位于指定数组索引处的 float32 类型的元素作为 F 类型(浮点型)加载到计算堆栈的顶部。 /// Ldelem_R4, /// /// 将位于指定数组索引处的 float64 类型的元素作为 F 类型(浮点型)加载到计算堆栈的顶部。 /// Ldelem_R8, /// /// 将位于指定数组索引处的包含对象引用的元素作为 O 类型(对象引用)加载到计算堆栈的顶部。 /// Ldelem_Ref, /// /// 用计算堆栈上的 native int 值替换给定索引处的数组元素。 /// Stelem_I, /// /// 用计算堆栈上的 int8 值替换给定索引处的数组元素。 /// Stelem_I1, /// /// 用计算堆栈上的 int16 值替换给定索引处的数组元素。 /// Stelem_I2, /// /// 用计算堆栈上的 int32 值替换给定索引处的数组元素。 /// Stelem_I4, /// /// 用计算堆栈上的 int64 值替换给定索引处的数组元素。 /// Stelem_I8, /// /// 用计算堆栈上的 float32 值替换给定索引处的数组元素。 /// Stelem_R4, /// /// 用计算堆栈上的 float64 值替换给定索引处的数组元素。 /// Stelem_R8, /// /// 用计算堆栈上的对象 ref 值(O 类型)替换给定索引处的数组元素。 /// Stelem_Ref, /// /// 按照指令中指定的类型,将指定数组索引中的元素加载到计算堆栈的顶部。 /// Ldelem_Any, /// /// 用计算堆栈中的值替换给定索引处的数组元素,其类型在指令中指定。 /// Stelem_Any, /// /// 将指令中指定类型的已装箱的表示形式转换成未装箱形式。 /// Unbox_Any, /// /// 将位于计算堆栈顶部的有符号值转换为有符号 int8 并将其扩展为 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_I1, /// /// 将位于计算堆栈顶部的有符号值转换为 unsigned int8 并将其扩展为 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_U1, /// /// 将位于计算堆栈顶部的有符号值转换为有符号 int16 并将其扩展为 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_I2, /// /// 将位于计算堆栈顶部的有符号值转换为 unsigned int16 并将其扩展为 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_U2, /// /// 将位于计算堆栈顶部的有符号值转换为有符号 int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_I4, /// /// 将位于计算堆栈顶部的有符号值转换为 unsigned int32,并在溢出时引发 OverflowException。 /// Conv_Ovf_U4, /// /// 将位于计算堆栈顶部的有符号值转换为有符号 int64,并在溢出时引发 OverflowException。 /// Conv_Ovf_I8, /// /// 将位于计算堆栈顶部的有符号值转换为 unsigned int64,并在溢出时引发 OverflowException。 /// Conv_Ovf_U8, /// /// 检索嵌入在类型化引用内的地址(& 类型)。 /// Refanyval, /// /// 如果值不是有限数,则引发 ArithmeticException。 /// Ckfinite, /// /// 将对特定类型实例的类型化引用推送到计算堆栈上。 /// Mkrefany, /// /// 将元数据标记转换为其运行时表示形式,并将其推送到计算堆栈上。 /// Ldtoken, /// /// 将位于计算堆栈顶部的值转换为 unsigned int16,然后将其扩展为 int32。 /// Conv_U2, /// /// 将位于计算堆栈顶部的值转换为 unsigned int8,然后将其扩展为 int32。 /// Conv_U1, /// /// 将位于计算堆栈顶部的值转换为 native int。 /// Conv_I, /// /// 将位于计算堆栈顶部的有符号值转换为有符号 native int,并在溢出时引发 OverflowException。 /// Conv_Ovf_I, /// /// 将位于计算堆栈顶部的有符号值转换为 unsigned native int,并在溢出时引发 OverflowException。 /// Conv_Ovf_U, /// /// 将两个整数相加,执行溢出检查,并且将结果推送到计算堆栈上。 /// Add_Ovf, /// /// 将两个无符号整数值相加,执行溢出检查,并且将结果推送到计算堆栈上。 /// Add_Ovf_Un, /// /// 将两个整数值相乘,执行溢出检查,并将结果推送到计算堆栈上。 /// Mul_Ovf, /// /// 将两个无符号整数值相乘,执行溢出检查,并将结果推送到计算堆栈上。 /// Mul_Ovf_Un, /// /// 从另一值中减去一个整数值,执行溢出检查,并且将结果推送到计算堆栈上。 /// Sub_Ovf, /// /// 从另一值中减去一个无符号整数值,执行溢出检查,并且将结果推送到计算堆栈上。 /// Sub_Ovf_Un, /// /// 将控制从异常块的 fault 或 finally 子句转移回公共语言结构 (CLI) 异常处理程序。 /// Endfinally, /// /// 退出受保护的代码区域,无条件将控制转移到特定目标指令。 /// Leave, /// /// 退出受保护的代码区域,无条件将控制转移到目标指令(缩写形式)。 /// Leave_S, /// /// 在所提供的地址存储 native int 类型的值。 /// Stind_I, /// /// 将位于计算堆栈顶部的值转换为 unsigned native int,然后将其扩展为 native int。 /// Conv_U, /// /// 返回指向当前方法的参数列表的非托管指针。 /// Arglist, /// /// 比较两个值。如果这两个值相等,则将整数值 1 (int32) 推送到计算堆栈上;否则,将 0 (int32) 推送到计算堆栈上。 /// Ceq, /// /// 比较两个值。如果第一个值大于第二个值,则将整数值 1 (int32) 推送到计算堆栈上;反之,将 0 (int32) 推送到计算堆栈上。 /// Cgt, /// /// 比较两个无符号的或不可排序的值。如果第一个值大于第二个值,则将整数值 1 (int32) 推送到计算堆栈上;反之,将 0 (int32) 推送到计算堆栈上。 /// Cgt_Un, /// /// 比较两个值。如果第一个值小于第二个值,则将整数值 1 (int32) 推送到计算堆栈上;反之,将 0 (int32) 推送到计算堆栈上。 /// Clt, /// /// 比较无符号的或不可排序的值 value1 和 value2。如果 value1 小于 value2,则将整数值 1 (int32 ) 推送到计算堆栈上;反之,将 0 ( int32 ) 推送到计算堆栈上。 /// Clt_Un, /// /// 将指向实现特定方法的本机代码的非托管指针(native int 类型)推送到计算堆栈上。 /// Ldftn, /// /// 将指向实现与指定对象关联的特定虚方法的本机代码的非托管指针(native int 类型)推送到计算堆栈上。 /// Ldvirtftn, /// /// 将参数(由指定索引值引用)加载到堆栈上。 /// Ldarg, /// /// 将参数地址加载到计算堆栈上。 /// Ldarga, /// /// 将位于计算堆栈顶部的值存储到位于指定索引的参数槽中。 /// Starg, /// /// 将指定索引处的局部变量加载到计算堆栈上。 /// Ldloc, /// /// 将位于特定索引处的局部变量的地址加载到计算堆栈上。 /// Ldloca, /// /// 从计算堆栈的顶部弹出当前值并将其存储到指定索引处的局部变量列表中。 /// Stloc, /// /// 从本地动态内存池分配特定数目的字节并将第一个分配的字节的地址(瞬态指针,* 类型)推送到计算堆栈上。 /// Localloc, /// /// 将控制从异常的 filter 子句转移回公共语言结构 (CLI) 异常处理程序。 /// Endfilter, /// /// 指示当前位于计算堆栈上的地址可能没有与紧接的 ldind、stind、ldfld、stfld、ldobj、stobj、initblk 或 cpblk 指令的自然大小对齐。 /// Unaligned, /// /// 指定当前位于计算堆栈顶部的地址可以是易失的,并且读取该位置的结果不能被缓存,或者对该地址的多个存储区不能被取消。 /// Volatile, /// /// 执行后缀的方法调用指令,以便在执行实际调用指令前移除当前方法的堆栈帧。 /// Tail, /// /// 将位于指定地址的值类型的每个字段初始化为空引用或适当的基元类型的 0。 /// Initobj, /// /// 约束要对其进行虚方法调用的类型。 /// Constrained, /// /// 将指定数目的字节从源地址复制到目标地址。 /// Cpblk, /// /// 将位于特定地址的内存的指定块初始化为给定大小和初始值。 /// Initblk, No, /// /// 再次引发当前异常。 /// Rethrow, /// /// 将提供的值类型的大小(以字节为单位)推送到计算堆栈上。 /// Sizeof, /// /// 检索嵌入在类型化引用内的类型标记。 /// Refanytype, /// /// 指定后面的数组地址操作在运行时不执行类型检查,并且返回可变性受限的托管指针。 /// Readonly, } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Stack/RuntimeStack.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.Method; using ILRuntime.CLR.TypeSystem; using ILRuntime.Other; using ILRuntime.Runtime.Intepreter; namespace ILRuntime.Runtime.Stack { unsafe public class RuntimeStack : IDisposable { ILIntepreter intepreter; StackObject* pointer; StackObject* endOfMemory; StackObject* valueTypePtr; IntPtr nativePointer; #if DEBUG IList managedStack = new List(32); #else IList managedStack = new UncheckedList(32); #endif Stack frames = new Stack(); const int MAXIMAL_STACK_OBJECTS = 1024 * 16; public Stack Frames { get { return frames; } } public RuntimeStack(ILIntepreter intepreter) { this.intepreter = intepreter; nativePointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(sizeof(StackObject) * MAXIMAL_STACK_OBJECTS); pointer = (StackObject*)nativePointer.ToPointer(); endOfMemory = Add(pointer, MAXIMAL_STACK_OBJECTS); valueTypePtr = endOfMemory - 1; } ~RuntimeStack() { Dispose(); } public StackObject* StackBase { get { return pointer; } } public StackObject* ValueTypeStackPointer { get { return valueTypePtr; } } public StackObject* ValueTypeStackBase { get { return endOfMemory - 1; } } public IList ManagedStack { get { return managedStack; } } public void ResetValueTypePointer() { valueTypePtr = endOfMemory - 1; } public void InitializeFrame(ILMethod method, StackObject* esp, out StackFrame res) { if (esp < pointer || esp >= endOfMemory) throw new StackOverflowException(); if (frames.Count > 0 && frames.Peek().BasePointer > esp) throw new StackOverflowException(); res = new StackFrame(); res.LocalVarPointer = esp; res.Method = method; #if DEBUG res.Address = new IntegerReference(); for (int i = 0; i < method.LocalVariableCount; i++) { var p = Add(esp, i); p->ObjectType = ObjectTypes.Null; } #endif res.BasePointer = method.LocalVariableCount > 0 ? Add(esp, method.LocalVariableCount + 1) : esp; res.ManagedStackBase = managedStack.Count; res.ValueTypeBasePointer = valueTypePtr; //frames.Push(res); } public void PushFrame(ref StackFrame frame) { frames.Push(frame); } public StackObject* PopFrame(ref StackFrame frame, StackObject* esp) { if (frames.Count > 0 && frames.Peek().BasePointer == frame.BasePointer) frames.Pop(); else throw new NotSupportedException(); StackObject* returnVal = esp - 1; var method = frame.Method; StackObject* ret = ILIntepreter.Minus(frame.LocalVarPointer, method.ParameterCount); int mStackBase = frame.ManagedStackBase; if (method.HasThis) ret--; if(method.ReturnType != intepreter.AppDomain.VoidType) { *ret = *returnVal; if(ret->ObjectType == ObjectTypes.Object) { ret->Value = mStackBase; managedStack[mStackBase] = managedStack[returnVal->Value]; mStackBase++; } else if(ret->ObjectType == ObjectTypes.ValueTypeObjectReference) { StackObject* oriAddr = frame.ValueTypeBasePointer; RelocateValueType(ret, ref frame.ValueTypeBasePointer, ref mStackBase); *(StackObject**)&ret->Value = oriAddr; } ret++; } #if DEBUG ((List)managedStack).RemoveRange(mStackBase, managedStack.Count - mStackBase); #else ((UncheckedList)managedStack).RemoveRange(mStackBase, managedStack.Count - mStackBase); #endif valueTypePtr = frame.ValueTypeBasePointer; return ret; } void RelocateValueType(StackObject* src, ref StackObject* dst, ref int mStackBase) { StackObject* descriptor = *(StackObject**)&src->Value; if (descriptor > dst) throw new StackOverflowException(); *dst = *descriptor; int cnt = descriptor->ValueLow; StackObject* endAddr = ILIntepreter.Minus(dst, cnt + 1); for(int i = 0; i < cnt; i++) { StackObject* addr = ILIntepreter.Minus(descriptor, i + 1); StackObject* tarVal = ILIntepreter.Minus(dst, i + 1); *tarVal = *addr; switch (addr->ObjectType) { case ObjectTypes.Object: case ObjectTypes.ArrayReference: case ObjectTypes.FieldReference: if (tarVal->Value >= mStackBase) { int oldIdx = addr->Value; tarVal->Value = mStackBase; managedStack[mStackBase] = managedStack[oldIdx]; mStackBase++; } break; case ObjectTypes.ValueTypeObjectReference: var newAddr = endAddr; RelocateValueType(addr, ref endAddr, ref mStackBase); *(StackObject**)&tarVal->Value = newAddr; break; } } dst = endAddr; } public void AllocValueType(StackObject* ptr, IType type) { if (type.IsValueType) { int fieldCount = 0; if(type is ILType) { fieldCount = ((ILType)type).TotalFieldCount; } else { fieldCount = ((CLRType)type).TotalFieldCount; } ptr->ObjectType = ObjectTypes.ValueTypeObjectReference; var dst = valueTypePtr; *(StackObject**)&ptr->Value = dst; dst->ObjectType = ObjectTypes.ValueTypeDescriptor; dst->Value = type.GetHashCode(); dst->ValueLow = fieldCount; valueTypePtr = ILIntepreter.Minus(valueTypePtr, fieldCount + 1); if (valueTypePtr <= StackBase) throw new StackOverflowException(); InitializeValueTypeObject(type, dst); } else throw new ArgumentException(type.FullName + " is not a value type.", "type"); } void InitializeValueTypeObject(IType type, StackObject* ptr) { if (type is ILType) { ILType t = (ILType)type; for (int i = 0; i < t.FieldTypes.Length; i++) { var ft = t.FieldTypes[i]; StackObject* val = ILIntepreter.Minus(ptr, t.FieldStartIndex + i + 1); if (ft.IsPrimitive) StackObject.Initialized(val, ft); else { if (ft.IsValueType) { AllocValueType(val, ft); } else { val->ObjectType = ObjectTypes.Object; val->Value = managedStack.Count; managedStack.Add(null); } } } if (type.BaseType != null && type.BaseType is ILType) InitializeValueTypeObject((ILType)type.BaseType, ptr); } else { CLRType t = (CLRType)type; var cnt = t.TotalFieldCount; for(int i = 0; i < cnt; i++) { var it = t.OrderedFieldTypes[i] as CLRType; StackObject* val = ILIntepreter.Minus(ptr, i + 1); if (it.IsPrimitive) StackObject.Initialized(val, it); else { if (it.IsValueType) { if (it.ValueTypeBinder != null) AllocValueType(val, it); else { val->ObjectType = ObjectTypes.Object; val->Value = managedStack.Count; managedStack.Add(it.CreateDefaultInstance()); } } else { val->ObjectType = ObjectTypes.Object; val->Value = managedStack.Count; managedStack.Add(null); } } } } } public void ClearValueTypeObject(IType type, StackObject* ptr) { if (type is ILType) { ILType t = (ILType)type; for (int i = 0; i < t.FieldTypes.Length; i++) { var ft = t.FieldTypes[i]; StackObject* val = ILIntepreter.Minus(ptr, t.FieldStartIndex + i + 1); if (ft.IsPrimitive) StackObject.Initialized(val, ft); else { switch (val->ObjectType) { case ObjectTypes.ValueTypeObjectReference: ClearValueTypeObject(ft, *(StackObject**)&val->Value); break; default: if (ft.IsValueType) { if(ft is ILType) { throw new NotImplementedException(); } else { managedStack[val->Value] = ((CLRType)ft).CreateDefaultInstance(); } } else managedStack[val->Value] = null; break; } } } if (type.BaseType != null && type.BaseType is ILType) ClearValueTypeObject((ILType)type.BaseType, ptr); } else { CLRType t = (CLRType)type; var cnt = t.TotalFieldCount; for (int i = 0; i < cnt; i++) { var vt = t.OrderedFieldTypes[i] as CLRType; StackObject* val = ILIntepreter.Minus(ptr, i + 1); if (vt.IsPrimitive) StackObject.Initialized(val, vt); else { switch (val->ObjectType) { case ObjectTypes.ValueTypeObjectReference: { var dst = *(StackObject**)&val->Value; ClearValueTypeObject(vt, *(StackObject**)&val->Value); } break; default: if (vt.IsValueType) { managedStack[val->Value] = vt.CreateDefaultInstance(); } else managedStack[val->Value] = null; break; } } } } } public void FreeValueTypeObject(StackObject* esp) { int start = int.MaxValue; int end = int.MinValue; StackObject* endAddr; CountValueTypeManaged(esp, ref start, ref end, &endAddr); if (endAddr == valueTypePtr) valueTypePtr = *(StackObject**)&esp->Value; else throw new NotSupportedException(); if (start != int.MaxValue) { if (end == managedStack.Count - 1) { #if DEBUG ((List)managedStack).RemoveRange(start, managedStack.Count - start); #else ((UncheckedList)managedStack).RemoveRange(start, managedStack.Count - start); #endif } else throw new NotSupportedException(); } } void CountValueTypeManaged(StackObject* esp, ref int start, ref int end, StackObject** endAddr) { StackObject* descriptor = *(StackObject**)&esp->Value; int cnt = descriptor->ValueLow; *endAddr = ILIntepreter.Minus(descriptor, cnt + 1); for (int i = 0; i < cnt; i++) { StackObject* addr = ILIntepreter.Minus(descriptor, i + 1); switch (addr->ObjectType) { case ObjectTypes.Object: case ObjectTypes.ArrayReference: case ObjectTypes.FieldReference: { if (start == int.MaxValue) { start = addr->Value; end = start; } else if (addr->Value == end + 1) end++; else throw new NotSupportedException(); } break; case ObjectTypes.ValueTypeObjectReference: CountValueTypeManaged(addr, ref start, ref end, endAddr); break; } } } public void Dispose() { if (nativePointer != IntPtr.Zero) { System.Runtime.InteropServices.Marshal.FreeHGlobal(nativePointer); nativePointer = IntPtr.Zero; } } StackObject* Add(StackObject* a, int b) { return (StackObject*)((long)a + sizeof(StackObject) * b); } } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Stack/StackFrame.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.Method; namespace ILRuntime.Runtime.Stack { public class IntegerReference { public int Value { get; set; } } unsafe public struct StackFrame { public ILMethod Method; public StackObject* LocalVarPointer; public StackObject* BasePointer; public StackObject* ValueTypeBasePointer; public IntegerReference Address; public int ManagedStackBase; } } ================================================ FILE: SGFUnity/ILRuntime/Runtime/Stack/StackObject.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.TypeSystem; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; namespace ILRuntime.Runtime.Stack { [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] public struct StackObject { public static StackObject Null = new StackObject() { ObjectType = ObjectTypes.Null, Value = -1, ValueLow = 0 }; public ObjectTypes ObjectType; public int Value; public int ValueLow; //IL2CPP can't process esp->ToObject() properly, so I can only use static function for this public static unsafe object ToObject(StackObject* esp, ILRuntime.Runtime.Enviorment.AppDomain appdomain, IList mStack) { switch (esp->ObjectType) { case ObjectTypes.Integer: return esp->Value; case ObjectTypes.Long: { return *(long*)&esp->Value; } case ObjectTypes.Float: { return *(float*)&esp->Value; } case ObjectTypes.Double: { return *(double*)&esp->Value; } case ObjectTypes.Object: return mStack[esp->Value]; case ObjectTypes.FieldReference: { ILTypeInstance instance = mStack[esp->Value] as ILTypeInstance; if (instance != null) { return instance[esp->ValueLow]; } else { var obj = mStack[esp->Value]; IType t = null; if (obj is CrossBindingAdaptorType) { t = appdomain.GetType(((CrossBindingAdaptor)((CrossBindingAdaptorType)obj).ILInstance.Type.FirstCLRBaseType).BaseCLRType); } else t = appdomain.GetType(obj.GetType()); return ((CLRType)t).GetFieldValue(esp->ValueLow, obj); } } case ObjectTypes.ArrayReference: { Array instance = mStack[esp->Value] as Array; return instance.GetValue(esp->ValueLow); } case ObjectTypes.StaticFieldReference: { var t = appdomain.GetType(esp->Value); if (t is CLR.TypeSystem.ILType) { CLR.TypeSystem.ILType type = (CLR.TypeSystem.ILType)t; return type.StaticInstance[esp->ValueLow]; } else { CLR.TypeSystem.CLRType type = (CLR.TypeSystem.CLRType)t; return type.GetFieldValue(esp->ValueLow, null); } } case ObjectTypes.StackObjectReference: { return ToObject((*(StackObject**)&esp->Value), appdomain, mStack); } case ObjectTypes.ValueTypeObjectReference: { StackObject* dst = *(StackObject**)&esp->Value; IType type = appdomain.GetType(dst->Value); if (type is ILType) { ILType iltype = (ILType)type; var ins = iltype.Instantiate(false); for (int i = 0; i < dst->ValueLow; i++) { var addr = ILIntepreter.Minus(dst, i + 1); ins.AssignFromStack(i, addr, appdomain, mStack); } return ins; } else { return ((CLRType)type).ValueTypeBinder.ToObject(dst, mStack); } } case ObjectTypes.Null: return null; default: throw new NotImplementedException(); } } public unsafe static void Initialized(ref StackObject esp, int idx, Type t, IType fieldType, IList mStack) { if (t.IsPrimitive) { if (t == typeof(int) || t == typeof(uint) || t == typeof(short) || t == typeof(ushort) || t == typeof(byte) || t == typeof(sbyte) || t == typeof(char) || t == typeof(bool)) { esp.ObjectType = ObjectTypes.Integer; esp.Value = 0; esp.ValueLow = 0; } else if (t == typeof(long) || t == typeof(ulong)) { esp.ObjectType = ObjectTypes.Long; esp.Value = 0; esp.ValueLow = 0; } else if (t == typeof(float)) { esp.ObjectType = ObjectTypes.Float; esp.Value = 0; esp.ValueLow = 0; } else if (t == typeof(double)) { esp.ObjectType = ObjectTypes.Double; esp.Value = 0; esp.ValueLow = 0; } else throw new NotImplementedException(); } else { if (fieldType.IsValueType) { esp.ObjectType = ObjectTypes.Object; esp.Value = idx; if (fieldType is CLRType) { mStack[idx] = ((CLRType)fieldType).CreateDefaultInstance(); } else { mStack[idx] = ((ILType)fieldType).Instantiate(); } } else esp = Null; } } //IL2CPP can't process esp->Initialized() properly, so I can only use static function for this public unsafe static void Initialized(StackObject* esp, IType type) { var t = type.TypeForCLR; if (type.IsPrimitive) { if (t == typeof(int) || t == typeof(uint) || t == typeof(short) || t == typeof(ushort) || t == typeof(byte) || t == typeof(sbyte) || t == typeof(char) || t == typeof(bool)) { esp->ObjectType = ObjectTypes.Integer; esp->Value = 0; esp->ValueLow = 0; } else if (t == typeof(long) || t == typeof(ulong)) { esp->ObjectType = ObjectTypes.Long; esp->Value = 0; esp->ValueLow = 0; } else if (t == typeof(float)) { esp->ObjectType = ObjectTypes.Float; esp->Value = 0; esp->ValueLow = 0; } else if (t == typeof(double)) { esp->ObjectType = ObjectTypes.Double; esp->Value = 0; esp->ValueLow = 0; } else throw new NotImplementedException(); } else { *esp = Null; } } } public enum ObjectTypes { Null, Integer, Long, Float, Double, StackObjectReference,//Value = pointer, StaticFieldReference, ValueTypeObjectReference, ValueTypeDescriptor, Object, FieldReference,//Value = objIdx, ValueLow = fieldIdx ArrayReference,//Value = objIdx, ValueLow = elemIdx } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono/Actions.cs ================================================ // // Actions.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // #if !NET_3_5 && !NET_4_0 namespace Mono { //delegate void Action (); delegate void Action (T1 arg1, T2 arg2); //delegate void Action (T1 arg1, T2 arg2, T3 arg3); //delegate void Action (T1 arg1, T2 arg2, T3 arg3, T4 arg4); } #endif ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono/Empty.cs ================================================ // // Empty.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using Mono.Collections.Generic; namespace Mono { static class Empty { public static readonly T [] Array = new T [0]; } } namespace Mono.Cecil { static partial class Mixin { public static bool IsNullOrEmpty (T [] self) { return self == null || self.Length == 0; } public static bool IsNullOrEmpty (Collection self) { return self == null || self.size == 0; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono/Funcs.cs ================================================ // // Funcs.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // #if !NET_3_5 && !NET_4_0 namespace Mono { delegate TResult Func (); delegate TResult Func (T arg1); delegate TResult Func (T1 arg1, T2 arg2); //delegate TResult Func (T1 arg1, T2 arg2, T3 arg3); //delegate TResult Func (T1 arg1, T2 arg2, T3 arg3, T4 arg4); } #endif ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/ArrayType.cs ================================================ // // ArrayType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Text; using Mono.Collections.Generic; using MD = Mono.Cecil.Metadata; namespace Mono.Cecil { public struct ArrayDimension { int? lower_bound; int? upper_bound; public int? LowerBound { get { return lower_bound; } set { lower_bound = value; } } public int? UpperBound { get { return upper_bound; } set { upper_bound = value; } } public bool IsSized { get { return lower_bound.HasValue || upper_bound.HasValue; } } public ArrayDimension (int? lowerBound, int? upperBound) { this.lower_bound = lowerBound; this.upper_bound = upperBound; } public override string ToString () { return !IsSized ? string.Empty : lower_bound + "..." + upper_bound; } } public sealed class ArrayType : TypeSpecification { Collection dimensions; public Collection Dimensions { get { if (dimensions != null) return dimensions; dimensions = new Collection (); dimensions.Add (new ArrayDimension ()); return dimensions; } } public int Rank { get { return dimensions == null ? 1 : dimensions.Count; } } public bool IsVector { get { if (dimensions == null) return true; if (dimensions.Count > 1) return false; var dimension = dimensions [0]; return !dimension.IsSized; } } public override bool IsValueType { get { return false; } set { throw new InvalidOperationException (); } } public override string Name { get { return base.Name + Suffix; } } public override string FullName { get { return base.FullName + Suffix; } } string Suffix { get { if (IsVector) return "[]"; var suffix = new StringBuilder (); suffix.Append ("["); for (int i = 0; i < dimensions.Count; i++) { if (i > 0) suffix.Append (","); suffix.Append (dimensions [i].ToString ()); } suffix.Append ("]"); return suffix.ToString (); } } public override bool IsArray { get { return true; } } public ArrayType (TypeReference type) : base (type) { Mixin.CheckType (type); this.etype = MD.ElementType.Array; } public ArrayType (TypeReference type, int rank) : this (type) { Mixin.CheckType (type); if (rank == 1) return; dimensions = new Collection (rank); for (int i = 0; i < rank; i++) dimensions.Add (new ArrayDimension ()); this.etype = MD.ElementType.Array; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/AssemblyDefinition.cs ================================================ // // AssemblyDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.IO; using Mono.Collections.Generic; namespace Mono.Cecil { public sealed class AssemblyDefinition : ICustomAttributeProvider, ISecurityDeclarationProvider { AssemblyNameDefinition name; internal ModuleDefinition main_module; Collection modules; Collection custom_attributes; Collection security_declarations; public AssemblyNameDefinition Name { get { return name; } set { name = value; } } public string FullName { get { return name != null ? name.FullName : string.Empty; } } public MetadataToken MetadataToken { get { return new MetadataToken(TokenType.Assembly, 1); } set { } } public Collection Modules { get { if (modules != null) return modules; if (main_module.HasImage) return main_module.Read(ref modules, this, (_, reader) => reader.ReadModules()); return modules = new Collection(1) { main_module }; } } public ModuleDefinition MainModule { get { return main_module; } } public MethodDefinition EntryPoint { get { return main_module.EntryPoint; } set { main_module.EntryPoint = value; } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return Mixin.GetHasCustomAttributes(this, main_module); } } public Collection CustomAttributes { get { return custom_attributes ?? (Mixin.GetCustomAttributes(this, ref custom_attributes, main_module)); } } public bool HasSecurityDeclarations { get { if (security_declarations != null) return security_declarations.Count > 0; return Mixin.GetHasSecurityDeclarations(this, main_module); } } public Collection SecurityDeclarations { get { return security_declarations ?? (Mixin.GetSecurityDeclarations(this, ref security_declarations, main_module)); } } internal AssemblyDefinition() { } public static AssemblyDefinition ReadAssembly(string fileName) { return ReadAssembly(ModuleDefinition.ReadModule(fileName)); } public static AssemblyDefinition ReadAssembly(string fileName, ReaderParameters parameters) { return ReadAssembly(ModuleDefinition.ReadModule(fileName, parameters)); } public static AssemblyDefinition ReadAssembly(Stream stream) { return ReadAssembly(ModuleDefinition.ReadModule(stream)); } public static AssemblyDefinition ReadAssembly(Stream stream, ReaderParameters parameters) { return ReadAssembly(ModuleDefinition.ReadModule(stream, parameters)); } static AssemblyDefinition ReadAssembly(ModuleDefinition module) { var assembly = module.Assembly; if (assembly == null) throw new ArgumentException(); return assembly; } public override string ToString() { return this.FullName; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/AssemblyFlags.cs ================================================ // // AssemblyFlags.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum AssemblyAttributes : uint { PublicKey = 0x0001, SideBySideCompatible = 0x0000, Retargetable = 0x0100, WindowsRuntime = 0x0200, DisableJITCompileOptimizer = 0x4000, EnableJITCompileTracking = 0x8000, } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/AssemblyHashAlgorithm.cs ================================================ // // AssemblyHashAlgorithm.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public enum AssemblyHashAlgorithm : uint { None = 0x0000, Reserved = 0x8003, // MD5 SHA1 = 0x8004 } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/AssemblyLinkedResource.cs ================================================ // // AssemblyLinkedResource.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { public sealed class AssemblyLinkedResource : Resource { AssemblyNameReference reference; public AssemblyNameReference Assembly { get { return reference; } set { reference = value; } } public override ResourceType ResourceType { get { return ResourceType.AssemblyLinked; } } public AssemblyLinkedResource (string name, ManifestResourceAttributes flags) : base (name, flags) { } public AssemblyLinkedResource (string name, ManifestResourceAttributes flags, AssemblyNameReference reference) : base (name, flags) { this.reference = reference; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/AssemblyNameDefinition.cs ================================================ // // AssemblyNameDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { public sealed class AssemblyNameDefinition : AssemblyNameReference { public override byte [] Hash { get { return Empty.Array; } } internal AssemblyNameDefinition () { this.token = new MetadataToken (TokenType.Assembly, 1); } public AssemblyNameDefinition (string name, Version version) : base (name, version) { this.token = new MetadataToken (TokenType.Assembly, 1); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/AssemblyNameReference.cs ================================================ // // AssemblyNameReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Globalization; using System.Security.Cryptography; using System.Text; namespace Mono.Cecil { public class AssemblyNameReference : IMetadataScope { string name; string culture; Version version; uint attributes; byte[] public_key; byte[] public_key_token; AssemblyHashAlgorithm hash_algorithm; byte[] hash; internal MetadataToken token; string full_name; public string Name { get { return name; } set { name = value; full_name = null; } } public string Culture { get { return culture; } set { culture = value; full_name = null; } } public Version Version { get { return version; } set { version = value; full_name = null; } } public AssemblyAttributes Attributes { get { return (AssemblyAttributes)attributes; } set { attributes = (uint)value; } } public bool HasPublicKey { get { return Mixin.GetAttributes(attributes,(uint)AssemblyAttributes.PublicKey); } set { attributes =Mixin.SetAttributes(attributes,(uint)AssemblyAttributes.PublicKey, value); } } public bool IsSideBySideCompatible { get { return Mixin.GetAttributes(attributes,(uint)AssemblyAttributes.SideBySideCompatible); } set { attributes =Mixin.SetAttributes(attributes,(uint)AssemblyAttributes.SideBySideCompatible, value); } } public bool IsRetargetable { get { return Mixin.GetAttributes(attributes,(uint)AssemblyAttributes.Retargetable); } set { attributes =Mixin.SetAttributes(attributes,(uint)AssemblyAttributes.Retargetable, value); } } public bool IsWindowsRuntime { get { return Mixin.GetAttributes(attributes,(uint)AssemblyAttributes.WindowsRuntime); } set { attributes =Mixin.SetAttributes(attributes,(uint)AssemblyAttributes.WindowsRuntime, value); } } public byte[] PublicKey { get { return public_key ?? Empty.Array; } set { public_key = value; HasPublicKey = !Mixin.IsNullOrEmpty(public_key); public_key_token = Empty.Array; full_name = null; } } public byte[] PublicKeyToken { get { if (Mixin.IsNullOrEmpty(public_key_token) && !Mixin.IsNullOrEmpty(public_key)) { var hash = HashPublicKey(); // we need the last 8 bytes in reverse order byte[] local_public_key_token = new byte[8]; Array.Copy(hash, (hash.Length - 8), local_public_key_token, 0, 8); Array.Reverse(local_public_key_token, 0, 8); public_key_token = local_public_key_token; // publish only once finished (required for thread-safety) } return public_key_token ?? Empty.Array; } set { public_key_token = value; full_name = null; } } byte[] HashPublicKey() { HashAlgorithm algorithm; switch (hash_algorithm) { case AssemblyHashAlgorithm.Reserved: throw new NotSupportedException(); default: // None default to SHA1 algorithm = new SHA1Managed(); break; } using (algorithm) return algorithm.ComputeHash(public_key); } public virtual MetadataScopeType MetadataScopeType { get { return MetadataScopeType.AssemblyNameReference; } } public string FullName { get { if (full_name != null) return full_name; const string sep = ", "; var builder = new StringBuilder(); builder.Append(name); if (version != null) { builder.Append(sep); builder.Append("Version="); builder.Append(version.ToString()); } builder.Append(sep); builder.Append("Culture="); builder.Append(string.IsNullOrEmpty(culture) ? "neutral" : culture); builder.Append(sep); builder.Append("PublicKeyToken="); var pk_token = PublicKeyToken; if (!Mixin.IsNullOrEmpty(pk_token) && pk_token.Length > 0) { for (int i = 0; i < pk_token.Length; i++) { builder.Append(pk_token[i].ToString("x2")); } } else builder.Append("null"); return full_name = builder.ToString(); } } public static AssemblyNameReference Parse(string fullName) { if (fullName == null) throw new ArgumentNullException("fullName"); if (fullName.Length == 0) throw new ArgumentException("Name can not be empty"); var name = new AssemblyNameReference(); var tokens = fullName.Split(','); for (int i = 0; i < tokens.Length; i++) { var token = tokens[i].Trim(); if (i == 0) { name.Name = token; continue; } var parts = token.Split('='); if (parts.Length != 2) throw new ArgumentException("Malformed name"); switch (parts[0].ToLowerInvariant()) { case "version": name.Version = new Version(parts[1]); break; case "culture": name.Culture = parts[1]; break; case "publickeytoken": var pk_token = parts[1]; if (pk_token == "null") break; name.PublicKeyToken = new byte[pk_token.Length / 2]; for (int j = 0; j < name.PublicKeyToken.Length; j++) name.PublicKeyToken[j] = Byte.Parse(pk_token.Substring(j * 2, 2), NumberStyles.HexNumber); break; } } return name; } public AssemblyHashAlgorithm HashAlgorithm { get { return hash_algorithm; } set { hash_algorithm = value; } } public virtual byte[] Hash { get { return hash; } set { hash = value; } } public MetadataToken MetadataToken { get { return token; } set { token = value; } } internal AssemblyNameReference() { } public AssemblyNameReference(string name, Version version) { if (name == null) throw new ArgumentNullException("name"); this.name = name; this.version = version; this.hash_algorithm = AssemblyHashAlgorithm.None; this.token = new MetadataToken(TokenType.AssemblyRef); } public override string ToString() { return this.FullName; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/AssemblyReader.cs ================================================ // // AssemblyReader.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using System.IO; using System.Text; using Mono.Collections.Generic; using Mono.Cecil.Cil; using Mono.Cecil.Metadata; using Mono.Cecil.PE; using RVA = System.UInt32; namespace Mono.Cecil { abstract class ModuleReader { readonly protected Image image; readonly protected ModuleDefinition module; protected ModuleReader(Image image, ReadingMode mode) { this.image = image; this.module = new ModuleDefinition(image); this.module.ReadingMode = mode; } protected abstract void ReadModule(); protected void ReadModuleManifest(MetadataReader reader) { reader.Populate(module); ReadAssembly(reader); } void ReadAssembly(MetadataReader reader) { var name = reader.ReadAssemblyNameDefinition(); if (name == null) { module.kind = ModuleKind.NetModule; return; } var assembly = new AssemblyDefinition(); assembly.Name = name; module.assembly = assembly; assembly.main_module = module; } public static ModuleDefinition CreateModuleFrom(Image image, ReaderParameters parameters) { var module = ReadModule(image, parameters); ReadSymbols(module, parameters); if (parameters.AssemblyResolver != null) module.assembly_resolver = parameters.AssemblyResolver; if (parameters.MetadataResolver != null) module.metadata_resolver = parameters.MetadataResolver; return module; } static void ReadSymbols(ModuleDefinition module, ReaderParameters parameters) { var symbol_reader_provider = parameters.SymbolReaderProvider; if (symbol_reader_provider == null && parameters.ReadSymbols) symbol_reader_provider = SymbolProvider.GetPlatformReaderProvider(); if (symbol_reader_provider != null) { module.SymbolReaderProvider = symbol_reader_provider; var reader = parameters.SymbolStream != null ? symbol_reader_provider.GetSymbolReader(module, parameters.SymbolStream) : symbol_reader_provider.GetSymbolReader(module, module.FullyQualifiedName); module.ReadSymbols(reader); } } static ModuleDefinition ReadModule(Image image, ReaderParameters parameters) { var reader = CreateModuleReader(image, parameters.ReadingMode); reader.ReadModule(); return reader.module; } static ModuleReader CreateModuleReader(Image image, ReadingMode mode) { switch (mode) { case ReadingMode.Immediate: return new ImmediateModuleReader(image); case ReadingMode.Deferred: return new DeferredModuleReader(image); default: throw new ArgumentException(); } } } sealed class ImmediateModuleReader : ModuleReader { public ImmediateModuleReader(Image image) : base(image, ReadingMode.Immediate) { } protected override void ReadModule() { this.module.Read(this.module, (module, reader) => { ReadModuleManifest(reader); ReadModule(module); return module; }); } public static void ReadModule(ModuleDefinition module) { if (module.HasAssemblyReferences) Read(module.AssemblyReferences); if (module.HasResources) Read(module.Resources); if (module.HasModuleReferences) Read(module.ModuleReferences); if (module.HasTypes) ReadTypes(module.Types); if (module.HasExportedTypes) Read(module.ExportedTypes); if (module.HasCustomAttributes) Read(module.CustomAttributes); var assembly = module.Assembly; if (assembly == null) return; if (assembly.HasCustomAttributes) Read(assembly.CustomAttributes); if (assembly.HasSecurityDeclarations) Read(assembly.SecurityDeclarations); } static void ReadTypes(Collection types) { for (int i = 0; i < types.Count; i++) ReadType(types[i]); } static void ReadType(TypeDefinition type) { ReadGenericParameters(type); if (type.HasInterfaces) Read(type.Interfaces); if (type.HasNestedTypes) ReadTypes(type.NestedTypes); if (type.HasLayoutInfo) Read(type.ClassSize); if (type.HasFields) ReadFields(type); if (type.HasMethods) ReadMethods(type); if (type.HasProperties) ReadProperties(type); if (type.HasEvents) ReadEvents(type); ReadSecurityDeclarations(type); ReadCustomAttributes(type); } static void ReadGenericParameters(IGenericParameterProvider provider) { if (!provider.HasGenericParameters) return; var parameters = provider.GenericParameters; for (int i = 0; i < parameters.Count; i++) { var parameter = parameters[i]; if (parameter.HasConstraints) Read(parameter.Constraints); if (parameter.HasCustomAttributes) Read(parameter.CustomAttributes); } } static void ReadSecurityDeclarations(ISecurityDeclarationProvider provider) { if (provider.HasSecurityDeclarations) Read(provider.SecurityDeclarations); } static void ReadCustomAttributes(ICustomAttributeProvider provider) { if (provider.HasCustomAttributes) Read(provider.CustomAttributes); } static void ReadFields(TypeDefinition type) { var fields = type.Fields; for (int i = 0; i < fields.Count; i++) { var field = fields[i]; if (field.HasConstant) Read(field.Constant); if (field.HasLayoutInfo) Read(field.Offset); if (field.RVA > 0) Read(field.InitialValue); if (field.HasMarshalInfo) Read(field.MarshalInfo); ReadCustomAttributes(field); } } static void ReadMethods(TypeDefinition type) { var methods = type.Methods; for (int i = 0; i < methods.Count; i++) { var method = methods[i]; ReadGenericParameters(method); if (method.HasParameters) ReadParameters(method); if (method.HasOverrides) Read(method.Overrides); if (method.IsPInvokeImpl) Read(method.PInvokeInfo); ReadSecurityDeclarations(method); ReadCustomAttributes(method); var return_type = method.MethodReturnType; if (return_type.HasConstant) Read(return_type.Constant); if (return_type.HasMarshalInfo) Read(return_type.MarshalInfo); ReadCustomAttributes(return_type); } } static void ReadParameters(MethodDefinition method) { var parameters = method.Parameters; for (int i = 0; i < parameters.Count; i++) { var parameter = parameters[i]; if (parameter.HasConstant) Read(parameter.Constant); if (parameter.HasMarshalInfo) Read(parameter.MarshalInfo); ReadCustomAttributes(parameter); } } static void ReadProperties(TypeDefinition type) { var properties = type.Properties; for (int i = 0; i < properties.Count; i++) { var property = properties[i]; Read(property.GetMethod); if (property.HasConstant) Read(property.Constant); ReadCustomAttributes(property); } } static void ReadEvents(TypeDefinition type) { var events = type.Events; for (int i = 0; i < events.Count; i++) { var @event = events[i]; Read(@event.AddMethod); ReadCustomAttributes(@event); } } static void Read(object collection) { } } sealed class DeferredModuleReader : ModuleReader { public DeferredModuleReader(Image image) : base(image, ReadingMode.Deferred) { } protected override void ReadModule() { this.module.Read(this.module, (module, reader) => { ReadModuleManifest(reader); return module; }); } } sealed class MetadataReader : ByteBuffer { readonly internal Image image; readonly internal ModuleDefinition module; readonly internal MetadataSystem metadata; internal IGenericContext context; internal CodeReader code; uint Position { get { return (uint)base.position; } set { base.position = (int)value; } } public MetadataReader(ModuleDefinition module) : base(module.Image.MetadataSection.Data) { this.image = module.Image; this.module = module; this.metadata = module.MetadataSystem; this.code = new CodeReader(image.MetadataSection, this); } int GetCodedIndexSize(CodedIndex index) { return image.GetCodedIndexSize(index); } uint ReadByIndexSize(int size) { if (size == 4) return ReadUInt32(); else return ReadUInt16(); } byte[] ReadBlob() { var blob_heap = image.BlobHeap; if (blob_heap == null) { position += 2; return Empty.Array; } return blob_heap.Read(ReadBlobIndex()); } byte[] ReadBlob(uint signature) { var blob_heap = image.BlobHeap; if (blob_heap == null) return Empty.Array; return blob_heap.Read(signature); } uint ReadBlobIndex() { var blob_heap = image.BlobHeap; return ReadByIndexSize(blob_heap != null ? blob_heap.IndexSize : 2); } string ReadString() { return image.StringHeap.Read(ReadByIndexSize(image.StringHeap.IndexSize)); } uint ReadStringIndex() { return ReadByIndexSize(image.StringHeap.IndexSize); } uint ReadTableIndex(Table table) { return ReadByIndexSize(image.GetTableIndexSize(table)); } MetadataToken ReadMetadataToken(CodedIndex index) { return Mixin.GetMetadataToken(index, ReadByIndexSize(GetCodedIndexSize(index))); } int MoveTo(Table table) { var info = image.TableHeap[table]; if (info.Length != 0) Position = info.Offset; return (int)info.Length; } bool MoveTo(Table table, uint row) { var info = image.TableHeap[table]; var length = info.Length; if (length == 0 || row > length) return false; Position = info.Offset + (info.RowSize * (row - 1)); return true; } public AssemblyNameDefinition ReadAssemblyNameDefinition() { if (MoveTo(Table.Assembly) == 0) return null; var name = new AssemblyNameDefinition(); name.HashAlgorithm = (AssemblyHashAlgorithm)ReadUInt32(); PopulateVersionAndFlags(name); name.PublicKey = ReadBlob(); PopulateNameAndCulture(name); return name; } public ModuleDefinition Populate(ModuleDefinition module) { if (MoveTo(Table.Module) == 0) return module; Advance(2); // Generation module.Name = ReadString(); module.Mvid = image.GuidHeap.Read(ReadByIndexSize(image.GuidHeap.IndexSize)); return module; } void InitializeAssemblyReferences() { if (metadata.AssemblyReferences != null) return; int length = MoveTo(Table.AssemblyRef); var references = metadata.AssemblyReferences = new AssemblyNameReference[length]; for (uint i = 0; i < length; i++) { var reference = new AssemblyNameReference(); reference.token = new MetadataToken(TokenType.AssemblyRef, i + 1); PopulateVersionAndFlags(reference); var key_or_token = ReadBlob(); if (reference.HasPublicKey) reference.PublicKey = key_or_token; else reference.PublicKeyToken = key_or_token; PopulateNameAndCulture(reference); reference.Hash = ReadBlob(); references[i] = reference; } } public Collection ReadAssemblyReferences() { InitializeAssemblyReferences(); return new Collection(metadata.AssemblyReferences); } public MethodDefinition ReadEntryPoint() { if (module.Image.EntryPointToken == 0) return null; var token = new MetadataToken(module.Image.EntryPointToken); return GetMethodDefinition(token.RID); } public Collection ReadModules() { var modules = new Collection(1); modules.Add(this.module); int length = MoveTo(Table.File); for (uint i = 1; i <= length; i++) { var attributes = (FileAttributes)ReadUInt32(); var name = ReadString(); ReadBlobIndex(); if (attributes != FileAttributes.ContainsMetaData) continue; var parameters = new ReaderParameters { ReadingMode = module.ReadingMode, SymbolReaderProvider = module.SymbolReaderProvider, }; modules.Add(ModuleDefinition.ReadModule( GetModuleFileName(name), parameters)); } return modules; } string GetModuleFileName(string name) { if (module.FullyQualifiedName == null) throw new NotSupportedException(); var path = Path.GetDirectoryName(module.FullyQualifiedName); return Path.Combine(path, name); } void InitializeModuleReferences() { if (metadata.ModuleReferences != null) return; int length = MoveTo(Table.ModuleRef); var references = metadata.ModuleReferences = new ModuleReference[length]; for (uint i = 0; i < length; i++) { var reference = new ModuleReference(ReadString()); reference.token = new MetadataToken(TokenType.ModuleRef, i + 1); references[i] = reference; } } public Collection ReadModuleReferences() { InitializeModuleReferences(); return new Collection(metadata.ModuleReferences); } public bool HasFileResource() { int length = MoveTo(Table.File); if (length == 0) return false; for (uint i = 1; i <= length; i++) if (ReadFileRecord(i).Col1 == FileAttributes.ContainsNoMetaData) return true; return false; } public Collection ReadResources() { int length = MoveTo(Table.ManifestResource); var resources = new Collection(length); for (int i = 1; i <= length; i++) { var offset = ReadUInt32(); var flags = (ManifestResourceAttributes)ReadUInt32(); var name = ReadString(); var implementation = ReadMetadataToken(CodedIndex.Implementation); Resource resource; if (implementation.RID == 0) { resource = new EmbeddedResource(name, flags, offset, this); } else if (implementation.TokenType == TokenType.AssemblyRef) { resource = new AssemblyLinkedResource(name, flags) { Assembly = (AssemblyNameReference)GetTypeReferenceScope(implementation), }; } else if (implementation.TokenType == TokenType.File) { var file_record = ReadFileRecord(implementation.RID); resource = new LinkedResource(name, flags) { File = file_record.Col2, hash = ReadBlob(file_record.Col3) }; } else throw new NotSupportedException(); resources.Add(resource); } return resources; } Row ReadFileRecord(uint rid) { var position = this.position; if (!MoveTo(Table.File, rid)) throw new ArgumentException(); var record = new Row( (FileAttributes)ReadUInt32(), ReadString(), ReadBlobIndex()); this.position = position; return record; } public MemoryStream GetManagedResourceStream(uint offset) { var rva = image.Resources.VirtualAddress; var section = image.GetSectionAtVirtualAddress(rva); var position = (rva - section.VirtualAddress) + offset; var buffer = section.Data; var length = buffer[position] | (buffer[position + 1] << 8) | (buffer[position + 2] << 16) | (buffer[position + 3] << 24); return new MemoryStream(buffer, (int)position + 4, length); } void PopulateVersionAndFlags(AssemblyNameReference name) { name.Version = new Version( ReadUInt16(), ReadUInt16(), ReadUInt16(), ReadUInt16()); name.Attributes = (AssemblyAttributes)ReadUInt32(); } void PopulateNameAndCulture(AssemblyNameReference name) { name.Name = ReadString(); name.Culture = ReadString(); } public TypeDefinitionCollection ReadTypes() { InitializeTypeDefinitions(); var mtypes = metadata.Types; var type_count = mtypes.Length - metadata.NestedTypes.Count; var types = new TypeDefinitionCollection(module, type_count); for (int i = 0; i < mtypes.Length; i++) { var type = mtypes[i]; if (IsNested(type.Attributes)) continue; types.Add(type); } if (image.HasTable(Table.MethodPtr) || image.HasTable(Table.FieldPtr)) CompleteTypes(); return types; } void CompleteTypes() { var types = metadata.Types; for (int i = 0; i < types.Length; i++) { var type = types[i]; InitializeCollection(type.Fields); InitializeCollection(type.Methods); } } void InitializeTypeDefinitions() { if (metadata.Types != null) return; InitializeNestedTypes(); InitializeFields(); InitializeMethods(); int length = MoveTo(Table.TypeDef); var types = metadata.Types = new TypeDefinition[length]; for (uint i = 0; i < length; i++) { if (types[i] != null) continue; types[i] = ReadType(i + 1); } } static bool IsNested(TypeAttributes attributes) { switch (attributes & TypeAttributes.VisibilityMask) { case TypeAttributes.NestedAssembly: case TypeAttributes.NestedFamANDAssem: case TypeAttributes.NestedFamily: case TypeAttributes.NestedFamORAssem: case TypeAttributes.NestedPrivate: case TypeAttributes.NestedPublic: return true; default: return false; } } public bool HasNestedTypes(TypeDefinition type) { uint[] mapping; InitializeNestedTypes(); if (!metadata.TryGetNestedTypeMapping(type, out mapping)) return false; return mapping.Length > 0; } public Collection ReadNestedTypes(TypeDefinition type) { InitializeNestedTypes(); uint[] mapping; if (!metadata.TryGetNestedTypeMapping(type, out mapping)) return new MemberDefinitionCollection(type); var nested_types = new MemberDefinitionCollection(type, mapping.Length); for (int i = 0; i < mapping.Length; i++) { var nested_type = GetTypeDefinition(mapping[i]); if (nested_type != null) nested_types.Add(nested_type); } metadata.RemoveNestedTypeMapping(type); return nested_types; } void InitializeNestedTypes() { if (metadata.NestedTypes != null) return; var length = MoveTo(Table.NestedClass); metadata.NestedTypes = new Dictionary(length); metadata.ReverseNestedTypes = new Dictionary(length); if (length == 0) return; for (int i = 1; i <= length; i++) { var nested = ReadTableIndex(Table.TypeDef); var declaring = ReadTableIndex(Table.TypeDef); AddNestedMapping(declaring, nested); } } void AddNestedMapping(uint declaring, uint nested) { metadata.SetNestedTypeMapping(declaring, AddMapping(metadata.NestedTypes, declaring, nested)); metadata.SetReverseNestedTypeMapping(nested, declaring); } static TValue[] AddMapping(Dictionary cache, TKey key, TValue value) { TValue[] mapped; if (!cache.TryGetValue(key, out mapped)) { mapped = new[] { value }; return mapped; } var new_mapped = new TValue[mapped.Length + 1]; Array.Copy(mapped, new_mapped, mapped.Length); new_mapped[mapped.Length] = value; return new_mapped; } TypeDefinition ReadType(uint rid) { if (!MoveTo(Table.TypeDef, rid)) return null; var attributes = (TypeAttributes)ReadUInt32(); var name = ReadString(); var @namespace = ReadString(); var type = new TypeDefinition(@namespace, name, attributes); type.token = new MetadataToken(TokenType.TypeDef, rid); type.scope = module; type.module = module; metadata.AddTypeDefinition(type); this.context = type; type.BaseType = GetTypeDefOrRef(ReadMetadataToken(CodedIndex.TypeDefOrRef)); type.fields_range = ReadFieldsRange(rid); type.methods_range = ReadMethodsRange(rid); if (IsNested(attributes)) type.DeclaringType = GetNestedTypeDeclaringType(type); return type; } TypeDefinition GetNestedTypeDeclaringType(TypeDefinition type) { uint declaring_rid; if (!metadata.TryGetReverseNestedTypeMapping(type, out declaring_rid)) return null; metadata.RemoveReverseNestedTypeMapping(type); return GetTypeDefinition(declaring_rid); } Range ReadFieldsRange(uint type_index) { return ReadListRange(type_index, Table.TypeDef, Table.Field); } Range ReadMethodsRange(uint type_index) { return ReadListRange(type_index, Table.TypeDef, Table.Method); } Range ReadListRange(uint current_index, Table current, Table target) { var list = new Range(); list.Start = ReadTableIndex(target); uint next_index; var current_table = image.TableHeap[current]; if (current_index == current_table.Length) next_index = image.TableHeap[target].Length + 1; else { var position = Position; Position += (uint)(current_table.RowSize - image.GetTableIndexSize(target)); next_index = ReadTableIndex(target); Position = position; } list.Length = next_index - list.Start; return list; } public Row ReadTypeLayout(TypeDefinition type) { InitializeTypeLayouts(); Row class_layout; var rid = type.token.RID; if (!metadata.ClassLayouts.TryGetValue(rid, out class_layout)) return new Row(Mixin.NoDataMarker, Mixin.NoDataMarker); type.PackingSize = (short)class_layout.Col1; type.ClassSize = (int)class_layout.Col2; metadata.ClassLayouts.Remove(rid); return new Row((short)class_layout.Col1, (int)class_layout.Col2); } void InitializeTypeLayouts() { if (metadata.ClassLayouts != null) return; int length = MoveTo(Table.ClassLayout); var class_layouts = metadata.ClassLayouts = new Dictionary>(length); for (uint i = 0; i < length; i++) { var packing_size = ReadUInt16(); var class_size = ReadUInt32(); var parent = ReadTableIndex(Table.TypeDef); class_layouts.Add(parent, new Row(packing_size, class_size)); } } public TypeReference GetTypeDefOrRef(MetadataToken token) { return (TypeReference)LookupToken(token); } public TypeDefinition GetTypeDefinition(uint rid) { InitializeTypeDefinitions(); var type = metadata.GetTypeDefinition(rid); if (type != null) return type; return ReadTypeDefinition(rid); } TypeDefinition ReadTypeDefinition(uint rid) { if (!MoveTo(Table.TypeDef, rid)) return null; return ReadType(rid); } void InitializeTypeReferences() { if (metadata.TypeReferences != null) return; metadata.TypeReferences = new TypeReference[image.GetTableLength(Table.TypeRef)]; } public TypeReference GetTypeReference(string scope, string full_name) { InitializeTypeReferences(); var length = metadata.TypeReferences.Length; for (uint i = 1; i <= length; i++) { var type = GetTypeReference(i); if (type.FullName != full_name) continue; if (string.IsNullOrEmpty(scope)) return type; if (type.Scope.Name == scope) return type; } return null; } TypeReference GetTypeReference(uint rid) { InitializeTypeReferences(); var type = metadata.GetTypeReference(rid); if (type != null) return type; return ReadTypeReference(rid); } TypeReference ReadTypeReference(uint rid) { if (!MoveTo(Table.TypeRef, rid)) return null; TypeReference declaring_type = null; IMetadataScope scope; var scope_token = ReadMetadataToken(CodedIndex.ResolutionScope); var name = ReadString(); var @namespace = ReadString(); var type = new TypeReference( @namespace, name, module, null); type.token = new MetadataToken(TokenType.TypeRef, rid); metadata.AddTypeReference(type); if (scope_token.TokenType == TokenType.TypeRef) { declaring_type = GetTypeDefOrRef(scope_token); scope = declaring_type != null ? declaring_type.Scope : module; } else scope = GetTypeReferenceScope(scope_token); type.scope = scope; type.DeclaringType = declaring_type; MetadataSystem.TryProcessPrimitiveTypeReference(type); return type; } IMetadataScope GetTypeReferenceScope(MetadataToken scope) { switch (scope.TokenType) { case TokenType.AssemblyRef: InitializeAssemblyReferences(); return metadata.AssemblyReferences[(int)scope.RID - 1]; case TokenType.ModuleRef: InitializeModuleReferences(); return metadata.ModuleReferences[(int)scope.RID - 1]; case TokenType.Module: return module; default: throw new NotSupportedException(); } } public IEnumerable GetTypeReferences() { InitializeTypeReferences(); var length = image.GetTableLength(Table.TypeRef); var type_references = new TypeReference[length]; for (uint i = 1; i <= length; i++) type_references[i - 1] = GetTypeReference(i); return type_references; } TypeReference GetTypeSpecification(uint rid) { if (!MoveTo(Table.TypeSpec, rid)) return null; var reader = ReadSignature(ReadBlobIndex()); var type = reader.ReadTypeSignature(); if (type.token.RID == 0) type.token = new MetadataToken(TokenType.TypeSpec, rid); return type; } SignatureReader ReadSignature(uint signature) { return new SignatureReader(signature, this); } public bool HasInterfaces(TypeDefinition type) { InitializeInterfaces(); MetadataToken[] mapping; return metadata.TryGetInterfaceMapping(type, out mapping); } public Collection ReadInterfaces(TypeDefinition type) { InitializeInterfaces(); MetadataToken[] mapping; if (!metadata.TryGetInterfaceMapping(type, out mapping)) return new Collection(); var interfaces = new Collection(mapping.Length); this.context = type; for (int i = 0; i < mapping.Length; i++) interfaces.Add(GetTypeDefOrRef(mapping[i])); metadata.RemoveInterfaceMapping(type); return interfaces; } void InitializeInterfaces() { if (metadata.Interfaces != null) return; int length = MoveTo(Table.InterfaceImpl); metadata.Interfaces = new Dictionary(length); for (int i = 0; i < length; i++) { var type = ReadTableIndex(Table.TypeDef); var @interface = ReadMetadataToken(CodedIndex.TypeDefOrRef); AddInterfaceMapping(type, @interface); } } void AddInterfaceMapping(uint type, MetadataToken @interface) { metadata.SetInterfaceMapping(type, AddMapping(metadata.Interfaces, type, @interface)); } public Collection ReadFields(TypeDefinition type) { var fields_range = type.fields_range; if (fields_range.Length == 0) return new MemberDefinitionCollection(type); var fields = new MemberDefinitionCollection(type, (int)fields_range.Length); this.context = type; if (!MoveTo(Table.FieldPtr, fields_range.Start)) { if (!MoveTo(Table.Field, fields_range.Start)) return fields; for (uint i = 0; i < fields_range.Length; i++) ReadField(fields_range.Start + i, fields); } else ReadPointers(Table.FieldPtr, Table.Field, fields_range, fields, ReadField); return fields; } void ReadField(uint field_rid, Collection fields) { var attributes = (FieldAttributes)ReadUInt16(); var name = ReadString(); var signature = ReadBlobIndex(); var field = new FieldDefinition(name, attributes, ReadFieldType(signature)); field.token = new MetadataToken(TokenType.Field, field_rid); metadata.AddFieldDefinition(field); if (IsDeleted(field)) return; fields.Add(field); } void InitializeFields() { if (metadata.Fields != null) return; metadata.Fields = new FieldDefinition[image.GetTableLength(Table.Field)]; } TypeReference ReadFieldType(uint signature) { var reader = ReadSignature(signature); const byte field_sig = 0x6; if (reader.ReadByte() != field_sig) throw new NotSupportedException(); return reader.ReadTypeSignature(); } public int ReadFieldRVA(FieldDefinition field) { InitializeFieldRVAs(); var rid = field.token.RID; RVA rva; if (!metadata.FieldRVAs.TryGetValue(rid, out rva)) return 0; var size = GetFieldTypeSize(field.FieldType); if (size == 0 || rva == 0) return 0; metadata.FieldRVAs.Remove(rid); field.InitialValue = GetFieldInitializeValue(size, rva); return (int)rva; } byte[] GetFieldInitializeValue(int size, RVA rva) { var section = image.GetSectionAtVirtualAddress(rva); if (section == null) return Empty.Array; var value = new byte[size]; Buffer.BlockCopy(section.Data, (int)(rva - section.VirtualAddress), value, 0, size); return value; } static int GetFieldTypeSize(TypeReference type) { int size = 0; switch (type.etype) { case ElementType.Boolean: case ElementType.U1: case ElementType.I1: size = 1; break; case ElementType.U2: case ElementType.I2: case ElementType.Char: size = 2; break; case ElementType.U4: case ElementType.I4: case ElementType.R4: size = 4; break; case ElementType.U8: case ElementType.I8: case ElementType.R8: size = 8; break; case ElementType.Ptr: case ElementType.FnPtr: size = IntPtr.Size; break; case ElementType.CModOpt: case ElementType.CModReqD: return GetFieldTypeSize(((IModifierType)type).ElementType); default: var field_type = Mixin.CheckedResolve(type); if (field_type.HasLayoutInfo) size = field_type.ClassSize; break; } return size; } void InitializeFieldRVAs() { if (metadata.FieldRVAs != null) return; int length = MoveTo(Table.FieldRVA); var field_rvas = metadata.FieldRVAs = new Dictionary(length); for (int i = 0; i < length; i++) { var rva = ReadUInt32(); var field = ReadTableIndex(Table.Field); field_rvas.Add(field, rva); } } public int ReadFieldLayout(FieldDefinition field) { InitializeFieldLayouts(); var rid = field.token.RID; uint offset; if (!metadata.FieldLayouts.TryGetValue(rid, out offset)) return Mixin.NoDataMarker; metadata.FieldLayouts.Remove(rid); return (int)offset; } void InitializeFieldLayouts() { if (metadata.FieldLayouts != null) return; int length = MoveTo(Table.FieldLayout); var field_layouts = metadata.FieldLayouts = new Dictionary(length); for (int i = 0; i < length; i++) { var offset = ReadUInt32(); var field = ReadTableIndex(Table.Field); field_layouts.Add(field, offset); } } public bool HasEvents(TypeDefinition type) { InitializeEvents(); Range range; if (!metadata.TryGetEventsRange(type, out range)) return false; return range.Length > 0; } public Collection ReadEvents(TypeDefinition type) { InitializeEvents(); Range range; if (!metadata.TryGetEventsRange(type, out range)) return new MemberDefinitionCollection(type); var events = new MemberDefinitionCollection(type, (int)range.Length); metadata.RemoveEventsRange(type); if (range.Length == 0) return events; this.context = type; if (!MoveTo(Table.EventPtr, range.Start)) { if (!MoveTo(Table.Event, range.Start)) return events; for (uint i = 0; i < range.Length; i++) ReadEvent(range.Start + i, events); } else ReadPointers(Table.EventPtr, Table.Event, range, events, ReadEvent); return events; } void ReadEvent(uint event_rid, Collection events) { var attributes = (EventAttributes)ReadUInt16(); var name = ReadString(); var event_type = GetTypeDefOrRef(ReadMetadataToken(CodedIndex.TypeDefOrRef)); var @event = new EventDefinition(name, attributes, event_type); @event.token = new MetadataToken(TokenType.Event, event_rid); if (IsDeleted(@event)) return; events.Add(@event); } void InitializeEvents() { if (metadata.Events != null) return; int length = MoveTo(Table.EventMap); metadata.Events = new Dictionary(length); for (uint i = 1; i <= length; i++) { var type_rid = ReadTableIndex(Table.TypeDef); Range events_range = ReadEventsRange(i); metadata.AddEventsRange(type_rid, events_range); } } Range ReadEventsRange(uint rid) { return ReadListRange(rid, Table.EventMap, Table.Event); } public bool HasProperties(TypeDefinition type) { InitializeProperties(); Range range; if (!metadata.TryGetPropertiesRange(type, out range)) return false; return range.Length > 0; } public Collection ReadProperties(TypeDefinition type) { InitializeProperties(); Range range; if (!metadata.TryGetPropertiesRange(type, out range)) return new MemberDefinitionCollection(type); metadata.RemovePropertiesRange(type); var properties = new MemberDefinitionCollection(type, (int)range.Length); if (range.Length == 0) return properties; this.context = type; if (!MoveTo(Table.PropertyPtr, range.Start)) { if (!MoveTo(Table.Property, range.Start)) return properties; for (uint i = 0; i < range.Length; i++) ReadProperty(range.Start + i, properties); } else ReadPointers(Table.PropertyPtr, Table.Property, range, properties, ReadProperty); return properties; } void ReadProperty(uint property_rid, Collection properties) { var attributes = (PropertyAttributes)ReadUInt16(); var name = ReadString(); var signature = ReadBlobIndex(); var reader = ReadSignature(signature); const byte property_signature = 0x8; var calling_convention = reader.ReadByte(); if ((calling_convention & property_signature) == 0) throw new NotSupportedException(); var has_this = (calling_convention & 0x20) != 0; reader.ReadCompressedUInt32(); // count var property = new PropertyDefinition(name, attributes, reader.ReadTypeSignature()); property.HasThis = has_this; property.token = new MetadataToken(TokenType.Property, property_rid); if (IsDeleted(property)) return; properties.Add(property); } void InitializeProperties() { if (metadata.Properties != null) return; int length = MoveTo(Table.PropertyMap); metadata.Properties = new Dictionary(length); for (uint i = 1; i <= length; i++) { var type_rid = ReadTableIndex(Table.TypeDef); var properties_range = ReadPropertiesRange(i); metadata.AddPropertiesRange(type_rid, properties_range); } } Range ReadPropertiesRange(uint rid) { return ReadListRange(rid, Table.PropertyMap, Table.Property); } MethodSemanticsAttributes ReadMethodSemantics(MethodDefinition method) { InitializeMethodSemantics(); Row row; if (!metadata.Semantics.TryGetValue(method.token.RID, out row)) return MethodSemanticsAttributes.None; var type = method.DeclaringType; switch (row.Col1) { case MethodSemanticsAttributes.AddOn: GetEvent(type, row.Col2).add_method = method; break; case MethodSemanticsAttributes.Fire: GetEvent(type, row.Col2).invoke_method = method; break; case MethodSemanticsAttributes.RemoveOn: GetEvent(type, row.Col2).remove_method = method; break; case MethodSemanticsAttributes.Getter: GetProperty(type, row.Col2).get_method = method; break; case MethodSemanticsAttributes.Setter: GetProperty(type, row.Col2).set_method = method; break; case MethodSemanticsAttributes.Other: switch (row.Col2.TokenType) { case TokenType.Event: { var @event = GetEvent(type, row.Col2); if (@event.other_methods == null) @event.other_methods = new Collection(); @event.other_methods.Add(method); break; } case TokenType.Property: { var property = GetProperty(type, row.Col2); if (property.other_methods == null) property.other_methods = new Collection(); property.other_methods.Add(method); break; } default: throw new NotSupportedException(); } break; default: throw new NotSupportedException(); } metadata.Semantics.Remove(method.token.RID); return row.Col1; } static EventDefinition GetEvent(TypeDefinition type, MetadataToken token) { if (token.TokenType != TokenType.Event) throw new ArgumentException(); return GetMember(type.Events, token); } static PropertyDefinition GetProperty(TypeDefinition type, MetadataToken token) { if (token.TokenType != TokenType.Property) throw new ArgumentException(); return GetMember(type.Properties, token); } static TMember GetMember(Collection members, MetadataToken token) where TMember : IMemberDefinition { for (int i = 0; i < members.Count; i++) { var member = members[i]; if (member.MetadataToken == token) return member; } throw new ArgumentException(); } void InitializeMethodSemantics() { if (metadata.Semantics != null) return; int length = MoveTo(Table.MethodSemantics); var semantics = metadata.Semantics = new Dictionary>(0); for (uint i = 0; i < length; i++) { var attributes = (MethodSemanticsAttributes)ReadUInt16(); var method_rid = ReadTableIndex(Table.Method); var association = ReadMetadataToken(CodedIndex.HasSemantics); semantics[method_rid] = new Row(attributes, association); } } public PropertyDefinition ReadMethods(PropertyDefinition property) { ReadAllSemantics(property.DeclaringType); return property; } public EventDefinition ReadMethods(EventDefinition @event) { ReadAllSemantics(@event.DeclaringType); return @event; } public MethodSemanticsAttributes ReadAllSemantics(MethodDefinition method) { ReadAllSemantics(method.DeclaringType); return method.SemanticsAttributes; } void ReadAllSemantics(TypeDefinition type) { var methods = type.Methods; for (int i = 0; i < methods.Count; i++) { var method = methods[i]; if (method.sem_attrs_ready) continue; method.sem_attrs = ReadMethodSemantics(method); method.sem_attrs_ready = true; } } Range ReadParametersRange(uint method_rid) { return ReadListRange(method_rid, Table.Method, Table.Param); } public Collection ReadMethods(TypeDefinition type) { var methods_range = type.methods_range; if (methods_range.Length == 0) return new MemberDefinitionCollection(type); var methods = new MemberDefinitionCollection(type, (int)methods_range.Length); if (!MoveTo(Table.MethodPtr, methods_range.Start)) { if (!MoveTo(Table.Method, methods_range.Start)) return methods; for (uint i = 0; i < methods_range.Length; i++) ReadMethod(methods_range.Start + i, methods); } else ReadPointers(Table.MethodPtr, Table.Method, methods_range, methods, ReadMethod); return methods; } void ReadPointers(Table ptr, Table table, Range range, Collection members, Action> reader) where TMember : IMemberDefinition { for (uint i = 0; i < range.Length; i++) { MoveTo(ptr, range.Start + i); var rid = ReadTableIndex(table); MoveTo(table, rid); reader(rid, members); } } static bool IsDeleted(IMemberDefinition member) { return member.IsSpecialName && member.Name == "_Deleted"; } void InitializeMethods() { if (metadata.Methods != null) return; metadata.Methods = new MethodDefinition[image.GetTableLength(Table.Method)]; } void ReadMethod(uint method_rid, Collection methods) { var method = new MethodDefinition(); method.rva = ReadUInt32(); method.ImplAttributes = (MethodImplAttributes)ReadUInt16(); method.Attributes = (MethodAttributes)ReadUInt16(); method.Name = ReadString(); method.token = new MetadataToken(TokenType.Method, method_rid); if (IsDeleted(method)) return; methods.Add(method); // attach method var signature = ReadBlobIndex(); var param_range = ReadParametersRange(method_rid); this.context = method; ReadMethodSignature(signature, method); metadata.AddMethodDefinition(method); if (param_range.Length == 0) return; var position = base.position; ReadParameters(method, param_range); base.position = position; } void ReadParameters(MethodDefinition method, Range param_range) { if (!MoveTo(Table.ParamPtr, param_range.Start)) { if (!MoveTo(Table.Param, param_range.Start)) return; for (uint i = 0; i < param_range.Length; i++) ReadParameter(param_range.Start + i, method); } else ReadParameterPointers(method, param_range); } void ReadParameterPointers(MethodDefinition method, Range range) { for (uint i = 0; i < range.Length; i++) { MoveTo(Table.ParamPtr, range.Start + i); var rid = ReadTableIndex(Table.Param); MoveTo(Table.Param, rid); ReadParameter(rid, method); } } void ReadParameter(uint param_rid, MethodDefinition method) { var attributes = (ParameterAttributes)ReadUInt16(); var sequence = ReadUInt16(); var name = ReadString(); var parameter = sequence == 0 ? method.MethodReturnType.Parameter : method.Parameters[sequence - 1]; parameter.token = new MetadataToken(TokenType.Param, param_rid); parameter.Name = name; parameter.Attributes = attributes; } void ReadMethodSignature(uint signature, IMethodSignature method) { var reader = ReadSignature(signature); reader.ReadMethodSignature(method); } public PInvokeInfo ReadPInvokeInfo(MethodDefinition method) { InitializePInvokes(); Row row; var rid = method.token.RID; if (!metadata.PInvokes.TryGetValue(rid, out row)) return null; metadata.PInvokes.Remove(rid); return new PInvokeInfo( row.Col1, image.StringHeap.Read(row.Col2), module.ModuleReferences[(int)row.Col3 - 1]); } void InitializePInvokes() { if (metadata.PInvokes != null) return; int length = MoveTo(Table.ImplMap); var pinvokes = metadata.PInvokes = new Dictionary>(length); for (int i = 1; i <= length; i++) { var attributes = (PInvokeAttributes)ReadUInt16(); var method = ReadMetadataToken(CodedIndex.MemberForwarded); var name = ReadStringIndex(); var scope = ReadTableIndex(Table.File); if (method.TokenType != TokenType.Method) continue; pinvokes.Add(method.RID, new Row(attributes, name, scope)); } } public bool HasGenericParameters(IGenericParameterProvider provider) { InitializeGenericParameters(); Range range; if (!metadata.TryGetGenericParameterRange(provider, out range)) return false; return range.Length > 0; } public Collection ReadGenericParameters(IGenericParameterProvider provider) { InitializeGenericParameters(); Range range; if (!metadata.TryGetGenericParameterRange(provider, out range) || !MoveTo(Table.GenericParam, range.Start)) return new GenericParameterCollection(provider); metadata.RemoveGenericParameterRange(provider); var generic_parameters = new GenericParameterCollection(provider, (int)range.Length); for (uint i = 0; i < range.Length; i++) { ReadUInt16(); // index var flags = (GenericParameterAttributes)ReadUInt16(); ReadMetadataToken(CodedIndex.TypeOrMethodDef); var name = ReadString(); var parameter = new GenericParameter(name, provider); parameter.token = new MetadataToken(TokenType.GenericParam, range.Start + i); parameter.Attributes = flags; generic_parameters.Add(parameter); } return generic_parameters; } void InitializeGenericParameters() { if (metadata.GenericParameters != null) return; metadata.GenericParameters = InitializeRanges( Table.GenericParam, () => { Advance(4); var next = ReadMetadataToken(CodedIndex.TypeOrMethodDef); ReadStringIndex(); return next; }); } Dictionary InitializeRanges(Table table, Func get_next) { int length = MoveTo(table); var ranges = new Dictionary(length); if (length == 0) return ranges; MetadataToken owner = MetadataToken.Zero; Range range = new Range(1, 0); for (uint i = 1; i <= length; i++) { var next = get_next(); if (i == 1) { owner = next; range.Length++; } else if (next != owner) { if (owner.RID != 0) ranges.Add(owner, range); range = new Range(i, 1); owner = next; } else range.Length++; } if (owner != MetadataToken.Zero && !ranges.ContainsKey(owner)) ranges.Add(owner, range); return ranges; } public bool HasGenericConstraints(GenericParameter generic_parameter) { InitializeGenericConstraints(); MetadataToken[] mapping; if (!metadata.TryGetGenericConstraintMapping(generic_parameter, out mapping)) return false; return mapping.Length > 0; } public Collection ReadGenericConstraints(GenericParameter generic_parameter) { InitializeGenericConstraints(); MetadataToken[] mapping; if (!metadata.TryGetGenericConstraintMapping(generic_parameter, out mapping)) return new Collection(); var constraints = new Collection(mapping.Length); this.context = (IGenericContext)generic_parameter.Owner; for (int i = 0; i < mapping.Length; i++) constraints.Add(GetTypeDefOrRef(mapping[i])); metadata.RemoveGenericConstraintMapping(generic_parameter); return constraints; } void InitializeGenericConstraints() { if (metadata.GenericConstraints != null) return; var length = MoveTo(Table.GenericParamConstraint); metadata.GenericConstraints = new Dictionary(length); for (int i = 1; i <= length; i++) AddGenericConstraintMapping( ReadTableIndex(Table.GenericParam), ReadMetadataToken(CodedIndex.TypeDefOrRef)); } void AddGenericConstraintMapping(uint generic_parameter, MetadataToken constraint) { metadata.SetGenericConstraintMapping( generic_parameter, AddMapping(metadata.GenericConstraints, generic_parameter, constraint)); } public bool HasOverrides(MethodDefinition method) { InitializeOverrides(); MetadataToken[] mapping; if (!metadata.TryGetOverrideMapping(method, out mapping)) return false; return mapping.Length > 0; } public Collection ReadOverrides(MethodDefinition method) { InitializeOverrides(); MetadataToken[] mapping; if (!metadata.TryGetOverrideMapping(method, out mapping)) return new Collection(); var overrides = new Collection(mapping.Length); this.context = method; for (int i = 0; i < mapping.Length; i++) overrides.Add((MethodReference)LookupToken(mapping[i])); metadata.RemoveOverrideMapping(method); return overrides; } void InitializeOverrides() { if (metadata.Overrides != null) return; var length = MoveTo(Table.MethodImpl); metadata.Overrides = new Dictionary(length); for (int i = 1; i <= length; i++) { ReadTableIndex(Table.TypeDef); var method = ReadMetadataToken(CodedIndex.MethodDefOrRef); if (method.TokenType != TokenType.Method) throw new NotSupportedException(); var @override = ReadMetadataToken(CodedIndex.MethodDefOrRef); AddOverrideMapping(method.RID, @override); } } void AddOverrideMapping(uint method_rid, MetadataToken @override) { metadata.SetOverrideMapping( method_rid, AddMapping(metadata.Overrides, method_rid, @override)); } public MethodBody ReadMethodBody(MethodDefinition method) { return code.ReadMethodBody(method); } public CallSite ReadCallSite(MetadataToken token) { if (!MoveTo(Table.StandAloneSig, token.RID)) return null; var signature = ReadBlobIndex(); var call_site = new CallSite(); ReadMethodSignature(signature, call_site); call_site.MetadataToken = token; return call_site; } public VariableDefinitionCollection ReadVariables(MetadataToken local_var_token) { if (!MoveTo(Table.StandAloneSig, local_var_token.RID)) return null; var reader = ReadSignature(ReadBlobIndex()); const byte local_sig = 0x7; if (reader.ReadByte() != local_sig) throw new NotSupportedException(); var count = reader.ReadCompressedUInt32(); if (count == 0) return null; var variables = new VariableDefinitionCollection((int)count); for (int i = 0; i < count; i++) variables.Add(new VariableDefinition(reader.ReadTypeSignature())); return variables; } public IMetadataTokenProvider LookupToken(MetadataToken token) { var rid = token.RID; if (rid == 0) return null; IMetadataTokenProvider element; var position = this.position; var context = this.context; switch (token.TokenType) { case TokenType.TypeDef: element = GetTypeDefinition(rid); break; case TokenType.TypeRef: element = GetTypeReference(rid); break; case TokenType.TypeSpec: element = GetTypeSpecification(rid); break; case TokenType.Field: element = GetFieldDefinition(rid); break; case TokenType.Method: element = GetMethodDefinition(rid); break; case TokenType.MemberRef: element = GetMemberReference(rid); break; case TokenType.MethodSpec: element = GetMethodSpecification(rid); break; default: return null; } this.position = position; this.context = context; return element; } public FieldDefinition GetFieldDefinition(uint rid) { InitializeTypeDefinitions(); var field = metadata.GetFieldDefinition(rid); if (field != null) return field; return LookupField(rid); } FieldDefinition LookupField(uint rid) { var type = metadata.GetFieldDeclaringType(rid); if (type == null) return null; InitializeCollection(type.Fields); return metadata.GetFieldDefinition(rid); } public MethodDefinition GetMethodDefinition(uint rid) { InitializeTypeDefinitions(); var method = metadata.GetMethodDefinition(rid); if (method != null) return method; return LookupMethod(rid); } MethodDefinition LookupMethod(uint rid) { var type = metadata.GetMethodDeclaringType(rid); if (type == null) return null; InitializeCollection(type.Methods); return metadata.GetMethodDefinition(rid); } MethodSpecification GetMethodSpecification(uint rid) { if (!MoveTo(Table.MethodSpec, rid)) return null; var element_method = (MethodReference)LookupToken( ReadMetadataToken(CodedIndex.MethodDefOrRef)); var signature = ReadBlobIndex(); var method_spec = ReadMethodSpecSignature(signature, element_method); method_spec.token = new MetadataToken(TokenType.MethodSpec, rid); return method_spec; } MethodSpecification ReadMethodSpecSignature(uint signature, MethodReference method) { var reader = ReadSignature(signature); const byte methodspec_sig = 0x0a; var call_conv = reader.ReadByte(); if (call_conv != methodspec_sig) throw new NotSupportedException(); var instance = new GenericInstanceMethod(method); reader.ReadGenericInstanceSignature(method, instance); return instance; } MemberReference GetMemberReference(uint rid) { InitializeMemberReferences(); var member = metadata.GetMemberReference(rid); if (member != null) return member; member = ReadMemberReference(rid); if (member != null && !member.ContainsGenericParameter) metadata.AddMemberReference(member); return member; } MemberReference ReadMemberReference(uint rid) { if (!MoveTo(Table.MemberRef, rid)) return null; var token = ReadMetadataToken(CodedIndex.MemberRefParent); var name = ReadString(); var signature = ReadBlobIndex(); MemberReference member; switch (token.TokenType) { case TokenType.TypeDef: case TokenType.TypeRef: case TokenType.TypeSpec: member = ReadTypeMemberReference(token, name, signature); break; case TokenType.Method: member = ReadMethodMemberReference(token, name, signature); break; default: throw new NotSupportedException(); } member.token = new MetadataToken(TokenType.MemberRef, rid); return member; } MemberReference ReadTypeMemberReference(MetadataToken type, string name, uint signature) { var declaring_type = GetTypeDefOrRef(type); if (!declaring_type.IsArray) this.context = declaring_type; var member = ReadMemberReferenceSignature(signature, declaring_type); member.Name = name; return member; } MemberReference ReadMemberReferenceSignature(uint signature, TypeReference declaring_type) { var reader = ReadSignature(signature); const byte field_sig = 0x6; if (reader.buffer[reader.position] == field_sig) { reader.position++; var field = new FieldReference(); field.DeclaringType = declaring_type; field.FieldType = reader.ReadTypeSignature(); return field; } else { var method = new MethodReference(); method.DeclaringType = declaring_type; reader.ReadMethodSignature(method); return method; } } MemberReference ReadMethodMemberReference(MetadataToken token, string name, uint signature) { var method = GetMethodDefinition(token.RID); this.context = method; var member = ReadMemberReferenceSignature(signature, method.DeclaringType); member.Name = name; return member; } void InitializeMemberReferences() { if (metadata.MemberReferences != null) return; metadata.MemberReferences = new MemberReference[image.GetTableLength(Table.MemberRef)]; } public IEnumerable GetMemberReferences() { InitializeMemberReferences(); var length = image.GetTableLength(Table.MemberRef); var type_system = module.TypeSystem; var context = new MethodReference(string.Empty, type_system.Void); context.DeclaringType = new TypeReference(string.Empty, string.Empty, module, type_system.Corlib); var member_references = new MemberReference[length]; for (uint i = 1; i <= length; i++) { this.context = context; member_references[i - 1] = GetMemberReference(i); } return member_references; } void InitializeConstants() { if (metadata.Constants != null) return; var length = MoveTo(Table.Constant); var constants = metadata.Constants = new Dictionary>(length); for (uint i = 1; i <= length; i++) { var type = (ElementType)ReadUInt16(); var owner = ReadMetadataToken(CodedIndex.HasConstant); var signature = ReadBlobIndex(); constants.Add(owner, new Row(type, signature)); } } public object ReadConstant(IConstantProvider owner) { InitializeConstants(); Row row; if (!metadata.Constants.TryGetValue(owner.MetadataToken, out row)) return Mixin.NoValue; metadata.Constants.Remove(owner.MetadataToken); switch (row.Col1) { case ElementType.Class: case ElementType.Object: return null; case ElementType.String: return ReadConstantString(ReadBlob(row.Col2)); default: return ReadConstantPrimitive(row.Col1, row.Col2); } } static string ReadConstantString(byte[] blob) { var length = blob.Length; if ((length & 1) == 1) length--; return Encoding.Unicode.GetString(blob, 0, length); } object ReadConstantPrimitive(ElementType type, uint signature) { var reader = ReadSignature(signature); return reader.ReadConstantSignature(type); } void InitializeCustomAttributes() { if (metadata.CustomAttributes != null) return; metadata.CustomAttributes = InitializeRanges( Table.CustomAttribute, () => { var next = ReadMetadataToken(CodedIndex.HasCustomAttribute); ReadMetadataToken(CodedIndex.CustomAttributeType); ReadBlobIndex(); return next; }); } public bool HasCustomAttributes(ICustomAttributeProvider owner) { InitializeCustomAttributes(); Range range; if (!metadata.TryGetCustomAttributeRange(owner, out range)) return false; return range.Length > 0; } public Collection ReadCustomAttributes(ICustomAttributeProvider owner) { InitializeCustomAttributes(); Range range; if (!metadata.TryGetCustomAttributeRange(owner, out range) || !MoveTo(Table.CustomAttribute, range.Start)) return new Collection(); var custom_attributes = new Collection((int)range.Length); for (int i = 0; i < range.Length; i++) { ReadMetadataToken(CodedIndex.HasCustomAttribute); var constructor = (MethodReference)LookupToken( ReadMetadataToken(CodedIndex.CustomAttributeType)); var signature = ReadBlobIndex(); custom_attributes.Add(new CustomAttribute(signature, constructor)); } metadata.RemoveCustomAttributeRange(owner); return custom_attributes; } public byte[] ReadCustomAttributeBlob(uint signature) { return ReadBlob(signature); } public void ReadCustomAttributeSignature(CustomAttribute attribute) { var reader = ReadSignature(attribute.signature); if (!reader.CanReadMore()) return; if (reader.ReadUInt16() != 0x0001) throw new InvalidOperationException(); var constructor = attribute.Constructor; if (constructor.HasParameters) reader.ReadCustomAttributeConstructorArguments(attribute, constructor.Parameters); if (!reader.CanReadMore()) return; var named = reader.ReadUInt16(); if (named == 0) return; reader.ReadCustomAttributeNamedArguments(named, ref attribute.fields, ref attribute.properties); } void InitializeMarshalInfos() { if (metadata.FieldMarshals != null) return; var length = MoveTo(Table.FieldMarshal); var marshals = metadata.FieldMarshals = new Dictionary(length); for (int i = 0; i < length; i++) { var token = ReadMetadataToken(CodedIndex.HasFieldMarshal); var signature = ReadBlobIndex(); if (token.RID == 0) continue; marshals.Add(token, signature); } } public bool HasMarshalInfo(IMarshalInfoProvider owner) { InitializeMarshalInfos(); return metadata.FieldMarshals.ContainsKey(owner.MetadataToken); } public MarshalInfo ReadMarshalInfo(IMarshalInfoProvider owner) { InitializeMarshalInfos(); uint signature; if (!metadata.FieldMarshals.TryGetValue(owner.MetadataToken, out signature)) return null; var reader = ReadSignature(signature); metadata.FieldMarshals.Remove(owner.MetadataToken); return reader.ReadMarshalInfo(); } void InitializeSecurityDeclarations() { if (metadata.SecurityDeclarations != null) return; metadata.SecurityDeclarations = InitializeRanges( Table.DeclSecurity, () => { ReadUInt16(); var next = ReadMetadataToken(CodedIndex.HasDeclSecurity); ReadBlobIndex(); return next; }); } public bool HasSecurityDeclarations(ISecurityDeclarationProvider owner) { InitializeSecurityDeclarations(); Range range; if (!metadata.TryGetSecurityDeclarationRange(owner, out range)) return false; return range.Length > 0; } public Collection ReadSecurityDeclarations(ISecurityDeclarationProvider owner) { InitializeSecurityDeclarations(); Range range; if (!metadata.TryGetSecurityDeclarationRange(owner, out range) || !MoveTo(Table.DeclSecurity, range.Start)) return new Collection(); var security_declarations = new Collection((int)range.Length); for (int i = 0; i < range.Length; i++) { var action = (SecurityAction)ReadUInt16(); ReadMetadataToken(CodedIndex.HasDeclSecurity); var signature = ReadBlobIndex(); security_declarations.Add(new SecurityDeclaration(action, signature, module)); } metadata.RemoveSecurityDeclarationRange(owner); return security_declarations; } public byte[] ReadSecurityDeclarationBlob(uint signature) { return ReadBlob(signature); } public void ReadSecurityDeclarationSignature(SecurityDeclaration declaration) { var signature = declaration.signature; var reader = ReadSignature(signature); if (reader.buffer[reader.position] != '.') { ReadXmlSecurityDeclaration(signature, declaration); return; } reader.position++; var count = reader.ReadCompressedUInt32(); var attributes = new Collection((int)count); for (int i = 0; i < count; i++) attributes.Add(reader.ReadSecurityAttribute()); declaration.security_attributes = attributes; } void ReadXmlSecurityDeclaration(uint signature, SecurityDeclaration declaration) { var blob = ReadBlob(signature); var attributes = new Collection(1); var attribute = new SecurityAttribute( module.TypeSystem.LookupType("System.Security.Permissions", "PermissionSetAttribute")); attribute.properties = new Collection(1); attribute.properties.Add( new CustomAttributeNamedArgument( "XML", new CustomAttributeArgument( module.TypeSystem.String, Encoding.Unicode.GetString(blob, 0, blob.Length)))); attributes.Add(attribute); declaration.security_attributes = attributes; } public Collection ReadExportedTypes() { var length = MoveTo(Table.ExportedType); if (length == 0) return new Collection(); var exported_types = new Collection(length); for (int i = 1; i <= length; i++) { var attributes = (TypeAttributes)ReadUInt32(); var identifier = ReadUInt32(); var name = ReadString(); var @namespace = ReadString(); var implementation = ReadMetadataToken(CodedIndex.Implementation); ExportedType declaring_type = null; IMetadataScope scope = null; switch (implementation.TokenType) { case TokenType.AssemblyRef: case TokenType.File: scope = GetExportedTypeScope(implementation); break; case TokenType.ExportedType: // FIXME: if the table is not properly sorted declaring_type = exported_types[(int)implementation.RID - 1]; break; } var exported_type = new ExportedType(@namespace, name, module, scope) { Attributes = attributes, Identifier = (int)identifier, DeclaringType = declaring_type, }; exported_type.token = new MetadataToken(TokenType.ExportedType, i); exported_types.Add(exported_type); } return exported_types; } IMetadataScope GetExportedTypeScope(MetadataToken token) { var position = this.position; IMetadataScope scope; switch (token.TokenType) { case TokenType.AssemblyRef: InitializeAssemblyReferences(); scope = metadata.AssemblyReferences[(int)token.RID - 1]; break; case TokenType.File: InitializeModuleReferences(); scope = GetModuleReferenceFromFile(token); break; default: throw new NotSupportedException(); } this.position = position; return scope; } ModuleReference GetModuleReferenceFromFile(MetadataToken token) { if (!MoveTo(Table.File, token.RID)) return null; ReadUInt32(); var file_name = ReadString(); var modules = module.ModuleReferences; ModuleReference reference; for (int i = 0; i < modules.Count; i++) { reference = modules[i]; if (reference.Name == file_name) return reference; } reference = new ModuleReference(file_name); modules.Add(reference); return reference; } static void InitializeCollection(object o) { } } sealed class SignatureReader : ByteBuffer { readonly MetadataReader reader; readonly uint start, sig_length; TypeSystem TypeSystem { get { return reader.module.TypeSystem; } } public SignatureReader(uint blob, MetadataReader reader) : base(reader.buffer) { this.reader = reader; MoveToBlob(blob); this.sig_length = ReadCompressedUInt32(); this.start = (uint)position; } void MoveToBlob(uint blob) { position = (int)(reader.image.BlobHeap.Offset + blob); } MetadataToken ReadTypeTokenSignature() { return Mixin.GetMetadataToken(CodedIndex.TypeDefOrRef, ReadCompressedUInt32()); } GenericParameter GetGenericParameter(GenericParameterType type, uint var) { var context = reader.context; int index = (int)var; if (context == null) return GetUnboundGenericParameter(type, index); IGenericParameterProvider provider; switch (type) { case GenericParameterType.Type: provider = context.Type; break; case GenericParameterType.Method: provider = context.Method; break; default: throw new NotSupportedException(); } if (!context.IsDefinition) CheckGenericContext(provider, index); if (index >= provider.GenericParameters.Count) return GetUnboundGenericParameter(type, index); return provider.GenericParameters[index]; } GenericParameter GetUnboundGenericParameter(GenericParameterType type, int index) { return new GenericParameter(index, type, reader.module); } static void CheckGenericContext(IGenericParameterProvider owner, int index) { var owner_parameters = owner.GenericParameters; for (int i = owner_parameters.Count; i <= index; i++) owner_parameters.Add(new GenericParameter(owner)); } public void ReadGenericInstanceSignature(IGenericParameterProvider provider, IGenericInstance instance) { var arity = ReadCompressedUInt32(); if (!provider.IsDefinition) CheckGenericContext(provider, (int)arity - 1); var instance_arguments = instance.GenericArguments; for (int i = 0; i < arity; i++) instance_arguments.Add(ReadTypeSignature()); } ArrayType ReadArrayTypeSignature() { var array = new ArrayType(ReadTypeSignature()); var rank = ReadCompressedUInt32(); var sizes = new uint[ReadCompressedUInt32()]; for (int i = 0; i < sizes.Length; i++) sizes[i] = ReadCompressedUInt32(); var low_bounds = new int[ReadCompressedUInt32()]; for (int i = 0; i < low_bounds.Length; i++) low_bounds[i] = ReadCompressedInt32(); array.Dimensions.Clear(); for (int i = 0; i < rank; i++) { int? lower = null, upper = null; if (i < low_bounds.Length) lower = low_bounds[i]; if (i < sizes.Length) upper = lower + (int)sizes[i] - 1; array.Dimensions.Add(new ArrayDimension(lower, upper)); } return array; } TypeReference GetTypeDefOrRef(MetadataToken token) { return reader.GetTypeDefOrRef(token); } public TypeReference ReadTypeSignature() { return ReadTypeSignature((ElementType)ReadByte()); } TypeReference ReadTypeSignature(ElementType etype) { switch (etype) { case ElementType.ValueType: { var value_type = GetTypeDefOrRef(ReadTypeTokenSignature()); value_type.IsValueType = true; return value_type; } case ElementType.Class: return GetTypeDefOrRef(ReadTypeTokenSignature()); case ElementType.Ptr: return new PointerType(ReadTypeSignature()); case ElementType.FnPtr: { var fptr = new FunctionPointerType(); ReadMethodSignature(fptr); return fptr; } case ElementType.ByRef: return new ByReferenceType(ReadTypeSignature()); case ElementType.Pinned: return new PinnedType(ReadTypeSignature()); case ElementType.SzArray: return new ArrayType(ReadTypeSignature()); case ElementType.Array: return ReadArrayTypeSignature(); case ElementType.CModOpt: return new OptionalModifierType( GetTypeDefOrRef(ReadTypeTokenSignature()), ReadTypeSignature()); case ElementType.CModReqD: return new RequiredModifierType( GetTypeDefOrRef(ReadTypeTokenSignature()), ReadTypeSignature()); case ElementType.Sentinel: return new SentinelType(ReadTypeSignature()); case ElementType.Var: return GetGenericParameter(GenericParameterType.Type, ReadCompressedUInt32()); case ElementType.MVar: return GetGenericParameter(GenericParameterType.Method, ReadCompressedUInt32()); case ElementType.GenericInst: { var is_value_type = ReadByte() == (byte)ElementType.ValueType; var element_type = GetTypeDefOrRef(ReadTypeTokenSignature()); var generic_instance = new GenericInstanceType(element_type); ReadGenericInstanceSignature(element_type, generic_instance); if (is_value_type) { generic_instance.IsValueType = true; element_type.GetElementType().IsValueType = true; } return generic_instance; } case ElementType.Object: return TypeSystem.Object; case ElementType.Void: return TypeSystem.Void; case ElementType.TypedByRef: return TypeSystem.TypedReference; case ElementType.I: return TypeSystem.IntPtr; case ElementType.U: return TypeSystem.UIntPtr; default: return GetPrimitiveType(etype); } } public void ReadMethodSignature(IMethodSignature method) { var calling_convention = ReadByte(); const byte has_this = 0x20; const byte explicit_this = 0x40; if ((calling_convention & has_this) != 0) { method.HasThis = true; calling_convention = (byte)(calling_convention & ~has_this); } if ((calling_convention & explicit_this) != 0) { method.ExplicitThis = true; calling_convention = (byte)(calling_convention & ~explicit_this); } method.CallingConvention = (MethodCallingConvention)calling_convention; var generic_context = method as MethodReference; if (generic_context != null && !generic_context.DeclaringType.IsArray) reader.context = generic_context; if ((calling_convention & 0x10) != 0) { var arity = ReadCompressedUInt32(); if (generic_context != null && !generic_context.IsDefinition) CheckGenericContext(generic_context, (int)arity - 1); } var param_count = ReadCompressedUInt32(); method.MethodReturnType.ReturnType = ReadTypeSignature(); if (param_count == 0) return; Collection parameters; var method_ref = method as MethodReference; if (method_ref != null) parameters = method_ref.parameters = new ParameterDefinitionCollection(method, (int)param_count); else parameters = method.Parameters; for (int i = 0; i < param_count; i++) parameters.Add(new ParameterDefinition(ReadTypeSignature())); } public object ReadConstantSignature(ElementType type) { return ReadPrimitiveValue(type); } public void ReadCustomAttributeConstructorArguments(CustomAttribute attribute, Collection parameters) { var count = parameters.Count; if (count == 0) return; attribute.arguments = new Collection(count); for (int i = 0; i < count; i++) attribute.arguments.Add( ReadCustomAttributeFixedArgument(parameters[i].ParameterType)); } CustomAttributeArgument ReadCustomAttributeFixedArgument(TypeReference type) { if (type.IsArray) return ReadCustomAttributeFixedArrayArgument((ArrayType)type); return ReadCustomAttributeElement(type); } public void ReadCustomAttributeNamedArguments(ushort count, ref Collection fields, ref Collection properties) { for (int i = 0; i < count; i++) ReadCustomAttributeNamedArgument(ref fields, ref properties); } void ReadCustomAttributeNamedArgument(ref Collection fields, ref Collection properties) { var kind = ReadByte(); var type = ReadCustomAttributeFieldOrPropType(); var name = ReadUTF8String(); Collection container; switch (kind) { case 0x53: container = GetCustomAttributeNamedArgumentCollection(ref fields); break; case 0x54: container = GetCustomAttributeNamedArgumentCollection(ref properties); break; default: throw new NotSupportedException(); } container.Add(new CustomAttributeNamedArgument(name, ReadCustomAttributeFixedArgument(type))); } static Collection GetCustomAttributeNamedArgumentCollection(ref Collection collection) { if (collection != null) return collection; return collection = new Collection(); } CustomAttributeArgument ReadCustomAttributeFixedArrayArgument(ArrayType type) { var length = ReadUInt32(); if (length == 0xffffffff) return new CustomAttributeArgument(type, null); if (length == 0) return new CustomAttributeArgument(type, Empty.Array); var arguments = new CustomAttributeArgument[length]; var element_type = type.ElementType; for (int i = 0; i < length; i++) arguments[i] = ReadCustomAttributeElement(element_type); return new CustomAttributeArgument(type, arguments); } CustomAttributeArgument ReadCustomAttributeElement(TypeReference type) { if (type.IsArray) return ReadCustomAttributeFixedArrayArgument((ArrayType)type); return new CustomAttributeArgument( type, type.etype == ElementType.Object ? ReadCustomAttributeElement(ReadCustomAttributeFieldOrPropType()) : ReadCustomAttributeElementValue(type)); } object ReadCustomAttributeElementValue(TypeReference type) { var etype = type.etype; switch (etype) { case ElementType.String: return ReadUTF8String(); case ElementType.None: if (Mixin.IsTypeOf(type,"System", "Type")) return ReadTypeReference(); return ReadCustomAttributeEnum(type); default: return ReadPrimitiveValue(etype); } } object ReadPrimitiveValue(ElementType type) { switch (type) { case ElementType.Boolean: return ReadByte() == 1; case ElementType.I1: return (sbyte)ReadByte(); case ElementType.U1: return ReadByte(); case ElementType.Char: return (char)ReadUInt16(); case ElementType.I2: return ReadInt16(); case ElementType.U2: return ReadUInt16(); case ElementType.I4: return ReadInt32(); case ElementType.U4: return ReadUInt32(); case ElementType.I8: return ReadInt64(); case ElementType.U8: return ReadUInt64(); case ElementType.R4: return ReadSingle(); case ElementType.R8: return ReadDouble(); default: throw new NotImplementedException(type.ToString()); } } TypeReference GetPrimitiveType(ElementType etype) { switch (etype) { case ElementType.Boolean: return TypeSystem.Boolean; case ElementType.Char: return TypeSystem.Char; case ElementType.I1: return TypeSystem.SByte; case ElementType.U1: return TypeSystem.Byte; case ElementType.I2: return TypeSystem.Int16; case ElementType.U2: return TypeSystem.UInt16; case ElementType.I4: return TypeSystem.Int32; case ElementType.U4: return TypeSystem.UInt32; case ElementType.I8: return TypeSystem.Int64; case ElementType.U8: return TypeSystem.UInt64; case ElementType.R4: return TypeSystem.Single; case ElementType.R8: return TypeSystem.Double; case ElementType.String: return TypeSystem.String; default: throw new NotImplementedException(etype.ToString()); } } TypeReference ReadCustomAttributeFieldOrPropType() { var etype = (ElementType)ReadByte(); switch (etype) { case ElementType.Boxed: return TypeSystem.Object; case ElementType.SzArray: return new ArrayType(ReadCustomAttributeFieldOrPropType()); case ElementType.Enum: return ReadTypeReference(); case ElementType.Type: return TypeSystem.LookupType("System", "Type"); default: return GetPrimitiveType(etype); } } public TypeReference ReadTypeReference() { return TypeParser.ParseType(reader.module, ReadUTF8String()); } object ReadCustomAttributeEnum(TypeReference enum_type) { try { TypeDefinition type = null; type = Mixin.CheckedResolve(enum_type); if (!type.IsEnum) throw new ArgumentException(); return ReadCustomAttributeElementValue(Mixin.GetEnumUnderlyingType(type)); } catch { //Resolve failed string name = enum_type.FullName + ", " + enum_type.scope.Name; Type type = Type.GetType(name); if (type == null || !type.IsEnum) return new ArgumentException(); var fields = type.GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public); Type eType = null; foreach(var i in fields) { eType = i.FieldType; break; } object val; if(eType == typeof(int)) { val = ReadPrimitiveValue(ElementType.I4); } else if (eType == typeof(long)) { val = ReadPrimitiveValue(ElementType.I8); } else if (eType == typeof(short)) { val = ReadPrimitiveValue(ElementType.I2); } else if (eType == typeof(byte)) { val = ReadPrimitiveValue(ElementType.U1); } else if (eType == typeof(uint)) { val = ReadPrimitiveValue(ElementType.U4); } else if (eType == typeof(ulong)) { val = ReadPrimitiveValue(ElementType.U8); } else if (eType == typeof(ushort)) { val = ReadPrimitiveValue(ElementType.U2); } else { val = ReadPrimitiveValue(ElementType.Void); } return Enum.ToObject(type, val); } } public SecurityAttribute ReadSecurityAttribute() { var attribute = new SecurityAttribute(ReadTypeReference()); ReadCompressedUInt32(); ReadCustomAttributeNamedArguments( (ushort)ReadCompressedUInt32(), ref attribute.fields, ref attribute.properties); return attribute; } public MarshalInfo ReadMarshalInfo() { var native = ReadNativeType(); switch (native) { case NativeType.Array: { var array = new ArrayMarshalInfo(); if (CanReadMore()) array.element_type = ReadNativeType(); if (CanReadMore()) array.size_parameter_index = (int)ReadCompressedUInt32(); if (CanReadMore()) array.size = (int)ReadCompressedUInt32(); if (CanReadMore()) array.size_parameter_multiplier = (int)ReadCompressedUInt32(); return array; } case NativeType.SafeArray: { var array = new SafeArrayMarshalInfo(); if (CanReadMore()) array.element_type = ReadVariantType(); return array; } case NativeType.FixedArray: { var array = new FixedArrayMarshalInfo(); if (CanReadMore()) array.size = (int)ReadCompressedUInt32(); if (CanReadMore()) array.element_type = ReadNativeType(); return array; } case NativeType.FixedSysString: { var sys_string = new FixedSysStringMarshalInfo(); if (CanReadMore()) sys_string.size = (int)ReadCompressedUInt32(); return sys_string; } case NativeType.CustomMarshaler: { var marshaler = new CustomMarshalInfo(); var guid_value = ReadUTF8String(); marshaler.guid = !string.IsNullOrEmpty(guid_value) ? new Guid(guid_value) : Guid.Empty; marshaler.unmanaged_type = ReadUTF8String(); marshaler.managed_type = ReadTypeReference(); marshaler.cookie = ReadUTF8String(); return marshaler; } default: return new MarshalInfo(native); } } NativeType ReadNativeType() { return (NativeType)ReadByte(); } VariantType ReadVariantType() { return (VariantType)ReadByte(); } string ReadUTF8String() { if (buffer[position] == 0xff) { position++; return null; } var length = (int)ReadCompressedUInt32(); if (length == 0) return string.Empty; var @string = Encoding.UTF8.GetString(buffer, position, buffer[position + length - 1] == 0 ? length - 1 : length); position += length; return @string; } public bool CanReadMore() { return position - start < sig_length; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/AssemblyWriter.cs ================================================ // // AssemblyWriter.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using System.IO; using System.Text; using Mono.Collections.Generic; using Mono.Cecil.Cil; using Mono.Cecil.Metadata; using Mono.Cecil.PE; using RVA = System.UInt32; using RID = System.UInt32; using CodedRID = System.UInt32; using StringIndex = System.UInt32; using BlobIndex = System.UInt32; namespace Mono.Cecil { } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/BaseAssemblyResolver.cs ================================================ // // BaseAssemblyResolver.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using System.IO; using System.Text; using Mono.Collections.Generic; namespace Mono.Cecil { public delegate AssemblyDefinition AssemblyResolveEventHandler (object sender, AssemblyNameReference reference); public sealed class AssemblyResolveEventArgs : EventArgs { readonly AssemblyNameReference reference; public AssemblyNameReference AssemblyReference { get { return reference; } } public AssemblyResolveEventArgs (AssemblyNameReference reference) { this.reference = reference; } } public class AssemblyResolutionException : FileNotFoundException { readonly AssemblyNameReference reference; public AssemblyNameReference AssemblyReference { get { return reference; } } public AssemblyResolutionException (AssemblyNameReference reference) : base (string.Format ("Failed to resolve assembly: '{0}'", reference)) { this.reference = reference; } } public abstract class BaseAssemblyResolver : IAssemblyResolver { static readonly bool on_mono = Type.GetType ("Mono.Runtime") != null; readonly Collection directories; public void AddSearchDirectory (string directory) { directories.Add (directory); } public void RemoveSearchDirectory (string directory) { directories.Remove (directory); } public string [] GetSearchDirectories () { var directories = new string [this.directories.size]; Array.Copy (this.directories.items, directories, directories.Length); return directories; } public virtual AssemblyDefinition Resolve (string fullName) { return Resolve (fullName, new ReaderParameters ()); } public virtual AssemblyDefinition Resolve (string fullName, ReaderParameters parameters) { if (fullName == null) throw new ArgumentNullException ("fullName"); return Resolve (AssemblyNameReference.Parse (fullName), parameters); } public event AssemblyResolveEventHandler ResolveFailure; protected BaseAssemblyResolver () { directories = new Collection (2) { ".", "bin" }; } AssemblyDefinition GetAssembly (string file, ReaderParameters parameters) { if (parameters.AssemblyResolver == null) parameters.AssemblyResolver = this; return ModuleDefinition.ReadModule (file, parameters).Assembly; } public virtual AssemblyDefinition Resolve (AssemblyNameReference name) { return Resolve (name, new ReaderParameters ()); } public virtual AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters) { if (name == null) throw new ArgumentNullException ("name"); if (parameters == null) parameters = new ReaderParameters (); var assembly = SearchDirectory (name, directories, parameters); if (assembly != null) return assembly; if (ResolveFailure != null) { assembly = ResolveFailure (this, name); if (assembly != null) return assembly; } throw new AssemblyResolutionException (name); } AssemblyDefinition SearchDirectory (AssemblyNameReference name, IEnumerable directories, ReaderParameters parameters) { var extensions = new [] { ".exe", ".dll" }; foreach (var directory in directories) { foreach (var extension in extensions) { string file = Path.Combine (directory, name.Name + extension); if (File.Exists (file)) return GetAssembly (file, parameters); } } return null; } static bool IsZero (Version version) { return version == null || (version.Major == 0 && version.Minor == 0 && version.Build == 0 && version.Revision == 0); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/CallSite.cs ================================================ // // CallSite.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Text; using Mono.Collections.Generic; namespace Mono.Cecil { public sealed class CallSite : IMethodSignature { readonly MethodReference signature; public bool HasThis { get { return signature.HasThis; } set { signature.HasThis = value; } } public bool ExplicitThis { get { return signature.ExplicitThis; } set { signature.ExplicitThis = value; } } public MethodCallingConvention CallingConvention { get { return signature.CallingConvention; } set { signature.CallingConvention = value; } } public bool HasParameters { get { return signature.HasParameters; } } public Collection Parameters { get { return signature.Parameters; } } public TypeReference ReturnType { get { return signature.MethodReturnType.ReturnType; } set { signature.MethodReturnType.ReturnType = value; } } public MethodReturnType MethodReturnType { get { return signature.MethodReturnType; } } public string Name { get { return string.Empty; } set { throw new InvalidOperationException (); } } public string Namespace { get { return string.Empty; } set { throw new InvalidOperationException (); } } public ModuleDefinition Module { get { return ReturnType.Module; } } public IMetadataScope Scope { get { return signature.ReturnType.Scope; } } public MetadataToken MetadataToken { get { return signature.token; } set { signature.token = value; } } public string FullName { get { var signature = new StringBuilder (); signature.Append (ReturnType.FullName); Mixin.MethodSignatureFullName (this,signature); return signature.ToString (); } } internal CallSite () { this.signature = new MethodReference (); this.signature.token = new MetadataToken (TokenType.Signature, 0); } public CallSite (TypeReference returnType) : this () { if (returnType == null) throw new ArgumentNullException ("returnType"); this.signature.ReturnType = returnType; } public override string ToString () { return FullName; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/CustomAttribute.cs ================================================ // // CustomAttribute.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Collections.Generic; namespace Mono.Cecil { public struct CustomAttributeArgument { readonly TypeReference type; readonly object value; public TypeReference Type { get { return type; } } public object Value { get { return value; } } public CustomAttributeArgument (TypeReference type, object value) { Mixin.CheckType (type); this.type = type; this.value = value; } } public struct CustomAttributeNamedArgument { readonly string name; readonly CustomAttributeArgument argument; public string Name { get { return name; } } public CustomAttributeArgument Argument { get { return argument; } } public CustomAttributeNamedArgument (string name, CustomAttributeArgument argument) { Mixin.CheckName (name); this.name = name; this.argument = argument; } } public interface ICustomAttribute { TypeReference AttributeType { get; } bool HasFields { get; } bool HasProperties { get; } Collection Fields { get; } Collection Properties { get; } } public sealed class CustomAttribute : ICustomAttribute { readonly internal uint signature; internal bool resolved; MethodReference constructor; byte [] blob; internal Collection arguments; internal Collection fields; internal Collection properties; public MethodReference Constructor { get { return constructor; } set { constructor = value; } } public TypeReference AttributeType { get { return constructor.DeclaringType; } } public bool IsResolved { get { return resolved; } } public bool HasConstructorArguments { get { Resolve (); return !Mixin.IsNullOrEmpty (arguments); } } public Collection ConstructorArguments { get { Resolve (); return arguments ?? (arguments = new Collection ()); } } public bool HasFields { get { Resolve (); return !Mixin.IsNullOrEmpty (fields); } } public Collection Fields { get { Resolve (); return fields ?? (fields = new Collection ()); } } public bool HasProperties { get { Resolve (); return !Mixin.IsNullOrEmpty (properties); } } public Collection Properties { get { Resolve (); return properties ?? (properties = new Collection ()); } } internal bool HasImage { get { return constructor != null && constructor.HasImage; } } internal ModuleDefinition Module { get { return constructor.Module; } } internal CustomAttribute (uint signature, MethodReference constructor) { this.signature = signature; this.constructor = constructor; this.resolved = false; } public CustomAttribute (MethodReference constructor) { this.constructor = constructor; this.resolved = true; } public CustomAttribute (MethodReference constructor, byte [] blob) { this.constructor = constructor; this.resolved = false; this.blob = blob; } public byte [] GetBlob () { if (blob != null) return blob; if (!HasImage) throw new NotSupportedException (); return Module.Read (ref blob, this, (attribute, reader) => reader.ReadCustomAttributeBlob (attribute.signature)); } void Resolve () { if (resolved || !HasImage) return; Module.Read (this, (attribute, reader) => { try { reader.ReadCustomAttributeSignature (attribute); resolved = true; } catch (ResolutionException) { if (arguments != null) arguments.Clear (); if (fields != null) fields.Clear (); if (properties != null) properties.Clear (); resolved = false; } return this; }); } } static partial class Mixin { public static void CheckName (string name) { if (name == null) throw new ArgumentNullException ("name"); if (name.Length == 0) throw new ArgumentException ("Empty name"); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/DefaultAssemblyResolver.cs ================================================ // // DefaultAssemblyResolver.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; namespace Mono.Cecil { public class DefaultAssemblyResolver : BaseAssemblyResolver { readonly IDictionary cache; public DefaultAssemblyResolver () { cache = new Dictionary (StringComparer.Ordinal); } public override AssemblyDefinition Resolve (AssemblyNameReference name) { if (name == null) throw new ArgumentNullException ("name"); AssemblyDefinition assembly; if (cache.TryGetValue (name.FullName, out assembly)) return assembly; assembly = base.Resolve (name); cache [name.FullName] = assembly; return assembly; } protected void RegisterAssembly (AssemblyDefinition assembly) { if (assembly == null) throw new ArgumentNullException ("assembly"); var name = assembly.Name.FullName; if (cache.ContainsKey (name)) return; cache [name] = assembly; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/EmbeddedResource.cs ================================================ // // EmbeddedResource.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.IO; namespace Mono.Cecil { public sealed class EmbeddedResource : Resource { readonly MetadataReader reader; uint? offset; byte [] data; Stream stream; public override ResourceType ResourceType { get { return ResourceType.Embedded; } } public EmbeddedResource (string name, ManifestResourceAttributes attributes, byte [] data) : base (name, attributes) { this.data = data; } public EmbeddedResource (string name, ManifestResourceAttributes attributes, Stream stream) : base (name, attributes) { this.stream = stream; } internal EmbeddedResource (string name, ManifestResourceAttributes attributes, uint offset, MetadataReader reader) : base (name, attributes) { this.offset = offset; this.reader = reader; } public Stream GetResourceStream () { if (stream != null) return stream; if (data != null) return new MemoryStream (data); if (offset.HasValue) return reader.GetManagedResourceStream (offset.Value); throw new InvalidOperationException (); } public byte [] GetResourceData () { if (stream != null) return ReadStream (stream); if (data != null) return data; if (offset.HasValue) return reader.GetManagedResourceStream (offset.Value).ToArray (); throw new InvalidOperationException (); } static byte [] ReadStream (Stream stream) { var length = (int) stream.Length; var data = new byte [length]; int offset = 0, read; while ((read = stream.Read (data, offset, length - offset)) > 0) offset += read; return data; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/EventAttributes.cs ================================================ // // EventAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum EventAttributes : ushort { None = 0x0000, SpecialName = 0x0200, // Event is special RTSpecialName = 0x0400 // CLI provides 'special' behavior, depending upon the name of the event } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/EventDefinition.cs ================================================ // // EventDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using Mono.Collections.Generic; namespace Mono.Cecil { public sealed class EventDefinition : EventReference, IMemberDefinition { ushort attributes; Collection custom_attributes; internal MethodDefinition add_method; internal MethodDefinition invoke_method; internal MethodDefinition remove_method; internal Collection other_methods; public EventAttributes Attributes { get { return (EventAttributes) attributes; } set { attributes = (ushort) value; } } public MethodDefinition AddMethod { get { if (add_method != null) return add_method; InitializeMethods (); return add_method; } set { add_method = value; } } public MethodDefinition InvokeMethod { get { if (invoke_method != null) return invoke_method; InitializeMethods (); return invoke_method; } set { invoke_method = value; } } public MethodDefinition RemoveMethod { get { if (remove_method != null) return remove_method; InitializeMethods (); return remove_method; } set { remove_method = value; } } public bool HasOtherMethods { get { if (other_methods != null) return other_methods.Count > 0; InitializeMethods (); return !Mixin.IsNullOrEmpty (other_methods); } } public Collection OtherMethods { get { if (other_methods != null) return other_methods; InitializeMethods (); if (other_methods != null) return other_methods; return other_methods = new Collection (); } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return Mixin.GetHasCustomAttributes(this, Module); } } public Collection CustomAttributes { get { return custom_attributes ?? (Mixin.GetCustomAttributes(this, ref custom_attributes, Module)); } } #region EventAttributes public bool IsSpecialName { get { return Mixin.GetAttributes(attributes,(ushort) EventAttributes.SpecialName); } set { attributes =Mixin.SetAttributes(attributes,(ushort) EventAttributes.SpecialName, value); } } public bool IsRuntimeSpecialName { get { return Mixin.GetAttributes(attributes,(ushort) FieldAttributes.RTSpecialName); } set { attributes =Mixin.SetAttributes(attributes,(ushort) FieldAttributes.RTSpecialName, value); } } #endregion public new TypeDefinition DeclaringType { get { return (TypeDefinition) base.DeclaringType; } set { base.DeclaringType = value; } } public override bool IsDefinition { get { return true; } } public EventDefinition (string name, EventAttributes attributes, TypeReference eventType) : base (name, eventType) { this.attributes = (ushort) attributes; this.token = new MetadataToken (TokenType.Event); } void InitializeMethods () { var module = this.Module; lock (module.SyncRoot) { if (add_method != null || invoke_method != null || remove_method != null) return; if (!Mixin.HasImage(module)) return; module.Read (this, (@event, reader) => reader.ReadMethods (@event)); } } public override EventDefinition Resolve () { return this; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/EventReference.cs ================================================ // // EventReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { public abstract class EventReference : MemberReference { TypeReference event_type; public TypeReference EventType { get { return event_type; } set { event_type = value; } } public override string FullName { get { return event_type.FullName + " " + MemberFullName (); } } protected EventReference (string name, TypeReference eventType) : base (name) { if (eventType == null) throw new ArgumentNullException ("eventType"); event_type = eventType; } public abstract EventDefinition Resolve (); } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/ExportedType.cs ================================================ // // ExportedType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { public class ExportedType : IMetadataTokenProvider { string @namespace; string name; uint attributes; IMetadataScope scope; ModuleDefinition module; int identifier; ExportedType declaring_type; internal MetadataToken token; public string Namespace { get { return @namespace; } set { @namespace = value; } } public string Name { get { return name; } set { name = value; } } public TypeAttributes Attributes { get { return (TypeAttributes) attributes; } set { attributes = (uint) value; } } public IMetadataScope Scope { get { if (declaring_type != null) return declaring_type.Scope; return scope; } } public ExportedType DeclaringType { get { return declaring_type; } set { declaring_type = value; } } public MetadataToken MetadataToken { get { return token; } set { token = value; } } public int Identifier { get { return identifier; } set { identifier = value; } } #region TypeAttributes public bool IsNotPublic { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NotPublic); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NotPublic, value); } } public bool IsPublic { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.Public); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.Public, value); } } public bool IsNestedPublic { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPublic); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPublic, value); } } public bool IsNestedPrivate { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPrivate); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPrivate, value); } } public bool IsNestedFamily { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamily); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamily, value); } } public bool IsNestedAssembly { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedAssembly); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedAssembly, value); } } public bool IsNestedFamilyAndAssembly { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamANDAssem); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamANDAssem, value); } } public bool IsNestedFamilyOrAssembly { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamORAssem); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamORAssem, value); } } public bool IsAutoLayout { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.AutoLayout); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.AutoLayout, value); } } public bool IsSequentialLayout { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.SequentialLayout); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.SequentialLayout, value); } } public bool IsExplicitLayout { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.ExplicitLayout); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.ExplicitLayout, value); } } public bool IsClass { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Class); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Class, value); } } public bool IsInterface { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Interface); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Interface, value); } } public bool IsAbstract { get { return Mixin.GetAttributes(attributes,(uint) TypeAttributes.Abstract); } set { attributes =Mixin.SetAttributes(attributes,(uint) TypeAttributes.Abstract, value); } } public bool IsSealed { get { return Mixin.GetAttributes(attributes,(uint) TypeAttributes.Sealed); } set { attributes =Mixin.SetAttributes(attributes,(uint) TypeAttributes.Sealed, value); } } public bool IsSpecialName { get { return Mixin.GetAttributes(attributes,(uint) TypeAttributes.SpecialName); } set { attributes =Mixin.SetAttributes(attributes,(uint) TypeAttributes.SpecialName, value); } } public bool IsImport { get { return Mixin.GetAttributes(attributes,(uint) TypeAttributes.Import); } set { attributes =Mixin.SetAttributes(attributes,(uint) TypeAttributes.Import, value); } } public bool IsSerializable { get { return Mixin.GetAttributes(attributes,(uint) TypeAttributes.Serializable); } set { attributes =Mixin.SetAttributes(attributes,(uint) TypeAttributes.Serializable, value); } } public bool IsAnsiClass { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AnsiClass); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AnsiClass, value); } } public bool IsUnicodeClass { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.UnicodeClass); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.UnicodeClass, value); } } public bool IsAutoClass { get { return Mixin.GetMaskedAttributes(attributes,(uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AutoClass); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AutoClass, value); } } public bool IsBeforeFieldInit { get { return Mixin.GetAttributes(attributes,(uint) TypeAttributes.BeforeFieldInit); } set { attributes =Mixin.SetAttributes(attributes,(uint) TypeAttributes.BeforeFieldInit, value); } } public bool IsRuntimeSpecialName { get { return Mixin.GetAttributes(attributes,(uint) TypeAttributes.RTSpecialName); } set { attributes =Mixin.SetAttributes(attributes,(uint) TypeAttributes.RTSpecialName, value); } } public bool HasSecurity { get { return Mixin.GetAttributes(attributes,(uint) TypeAttributes.HasSecurity); } set { attributes =Mixin.SetAttributes(attributes,(uint) TypeAttributes.HasSecurity, value); } } #endregion public bool IsForwarder { get { return Mixin.GetAttributes(attributes,(uint) TypeAttributes.Forwarder); } set { attributes =Mixin.SetAttributes(attributes,(uint) TypeAttributes.Forwarder, value); } } public string FullName { get { if (declaring_type != null) return declaring_type.FullName + "/" + name; if (string.IsNullOrEmpty (@namespace)) return name; return @namespace + "." + name; } } public ExportedType (string @namespace, string name, ModuleDefinition module, IMetadataScope scope) { this.@namespace = @namespace; this.name = name; this.scope = scope; this.module = module; } public override string ToString () { return FullName; } public TypeDefinition Resolve () { return module.Resolve (CreateReference ()); } internal TypeReference CreateReference () { return new TypeReference (@namespace, name, module, scope) { DeclaringType = declaring_type != null ? declaring_type.CreateReference () : null, }; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/FieldAttributes.cs ================================================ // // FieldAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum FieldAttributes : ushort { FieldAccessMask = 0x0007, CompilerControlled = 0x0000, // Member not referenceable Private = 0x0001, // Accessible only by the parent type FamANDAssem = 0x0002, // Accessible by sub-types only in this assembly Assembly = 0x0003, // Accessible by anyone in the Assembly Family = 0x0004, // Accessible only by type and sub-types FamORAssem = 0x0005, // Accessible by sub-types anywhere, plus anyone in the assembly Public = 0x0006, // Accessible by anyone who has visibility to this scope field contract attributes Static = 0x0010, // Defined on type, else per instance InitOnly = 0x0020, // Field may only be initialized, not written after init Literal = 0x0040, // Value is compile time constant NotSerialized = 0x0080, // Field does not have to be serialized when type is remoted SpecialName = 0x0200, // Field is special // Interop Attributes PInvokeImpl = 0x2000, // Implementation is forwarded through PInvoke // Additional flags RTSpecialName = 0x0400, // CLI provides 'special' behavior, depending upon the name of the field HasFieldMarshal = 0x1000, // Field has marshalling information HasDefault = 0x8000, // Field has default HasFieldRVA = 0x0100 // Field has RVA } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/FieldDefinition.cs ================================================ // // FieldDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using Mono.Collections.Generic; namespace Mono.Cecil { public sealed class FieldDefinition : FieldReference, IMemberDefinition, IConstantProvider, IMarshalInfoProvider { ushort attributes; Collection custom_attributes; int offset = Mixin.NotResolvedMarker; internal int rva = Mixin.NotResolvedMarker; byte [] initial_value; object constant = Mixin.NotResolved; MarshalInfo marshal_info; void ResolveLayout () { if (offset != Mixin.NotResolvedMarker) return; if (!HasImage) { offset = Mixin.NoDataMarker; return; } offset = Module.Read (this, (field, reader) => reader.ReadFieldLayout (field)); } public bool HasLayoutInfo { get { if (offset >= 0) return true; ResolveLayout (); return offset >= 0; } } public int Offset { get { if (offset >= 0) return offset; ResolveLayout (); return offset >= 0 ? offset : -1; } set { offset = value; } } void ResolveRVA () { if (rva != Mixin.NotResolvedMarker) return; if (!HasImage) return; rva = Module.Read (this, (field, reader) => reader.ReadFieldRVA (field)); } public int RVA { get { if (rva > 0) return rva; ResolveRVA (); return rva > 0 ? rva : 0; } } public byte [] InitialValue { get { if (initial_value != null) return initial_value; ResolveRVA (); if (initial_value == null) initial_value = Empty.Array; return initial_value; } set { initial_value = value; } } public FieldAttributes Attributes { get { return (FieldAttributes) attributes; } set { attributes = (ushort) value; } } public bool HasConstant { get { Mixin.ResolveConstant(this, ref constant, Module); return constant != Mixin.NoValue; } set { if (!value) constant = Mixin.NoValue; } } public object Constant { get { return HasConstant ? constant : null; } set { constant = value; } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return Mixin.GetHasCustomAttributes(this, Module); } } public Collection CustomAttributes { get { return custom_attributes ?? (Mixin.GetCustomAttributes(this, ref custom_attributes, Module)); } } public bool HasMarshalInfo { get { if (marshal_info != null) return true; return Mixin.GetHasMarshalInfo(this, Module); } } public MarshalInfo MarshalInfo { get { return marshal_info ?? (Mixin.GetMarshalInfo(this, ref marshal_info, Module)); } set { marshal_info = value; } } #region FieldAttributes public bool IsCompilerControlled { get { return Mixin.GetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.CompilerControlled); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.CompilerControlled, value); } } public bool IsPrivate { get { return Mixin.GetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Private); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Private, value); } } public bool IsFamilyAndAssembly { get { return Mixin.GetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.FamANDAssem); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.FamANDAssem, value); } } public bool IsAssembly { get { return Mixin.GetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Assembly); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Assembly, value); } } public bool IsFamily { get { return Mixin.GetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Family); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Family, value); } } public bool IsFamilyOrAssembly { get { return Mixin.GetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.FamORAssem); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.FamORAssem, value); } } public bool IsPublic { get { return Mixin.GetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Public); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Public, value); } } public bool IsStatic { get { return Mixin.GetAttributes(attributes,(ushort) FieldAttributes.Static); } set { attributes =Mixin.SetAttributes(attributes,(ushort) FieldAttributes.Static, value); } } public bool IsInitOnly { get { return Mixin.GetAttributes(attributes,(ushort) FieldAttributes.InitOnly); } set { attributes =Mixin.SetAttributes(attributes,(ushort) FieldAttributes.InitOnly, value); } } public bool IsLiteral { get { return Mixin.GetAttributes(attributes,(ushort) FieldAttributes.Literal); } set { attributes =Mixin.SetAttributes(attributes,(ushort) FieldAttributes.Literal, value); } } public bool IsNotSerialized { get { return Mixin.GetAttributes(attributes,(ushort) FieldAttributes.NotSerialized); } set { attributes =Mixin.SetAttributes(attributes,(ushort) FieldAttributes.NotSerialized, value); } } public bool IsSpecialName { get { return Mixin.GetAttributes(attributes,(ushort) FieldAttributes.SpecialName); } set { attributes =Mixin.SetAttributes(attributes,(ushort) FieldAttributes.SpecialName, value); } } public bool IsPInvokeImpl { get { return Mixin.GetAttributes(attributes,(ushort) FieldAttributes.PInvokeImpl); } set { attributes =Mixin.SetAttributes(attributes,(ushort) FieldAttributes.PInvokeImpl, value); } } public bool IsRuntimeSpecialName { get { return Mixin.GetAttributes(attributes,(ushort) FieldAttributes.RTSpecialName); } set { attributes =Mixin.SetAttributes(attributes,(ushort) FieldAttributes.RTSpecialName, value); } } public bool HasDefault { get { return Mixin.GetAttributes(attributes,(ushort) FieldAttributes.HasDefault); } set { attributes =Mixin.SetAttributes(attributes,(ushort) FieldAttributes.HasDefault, value); } } #endregion public override bool IsDefinition { get { return true; } } public new TypeDefinition DeclaringType { get { return (TypeDefinition) base.DeclaringType; } set { base.DeclaringType = value; } } public FieldDefinition (string name, FieldAttributes attributes, TypeReference fieldType) : base (name, fieldType) { this.attributes = (ushort) attributes; } public override FieldDefinition Resolve () { return this; } } static partial class Mixin { public const int NotResolvedMarker = -2; public const int NoDataMarker = -1; } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/FieldReference.cs ================================================ // // FieldReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { public class FieldReference : MemberReference { TypeReference field_type; public TypeReference FieldType { get { return field_type; } set { field_type = value; } } public override string FullName { get { return field_type.FullName + " " + MemberFullName (); } } internal override bool ContainsGenericParameter { get { return field_type.ContainsGenericParameter || base.ContainsGenericParameter; } } internal FieldReference () { this.token = new MetadataToken (TokenType.MemberRef); } public FieldReference (string name, TypeReference fieldType) : base (name) { if (fieldType == null) throw new ArgumentNullException ("fieldType"); this.field_type = fieldType; this.token = new MetadataToken (TokenType.MemberRef); } public FieldReference (string name, TypeReference fieldType, TypeReference declaringType) : this (name, fieldType) { if (declaringType == null) throw new ArgumentNullException("declaringType"); this.DeclaringType = declaringType; } public virtual FieldDefinition Resolve () { var module = this.Module; if (module == null) throw new NotSupportedException (); return module.Resolve (this); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/FileAttributes.cs ================================================ // // FileAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { enum FileAttributes : uint { ContainsMetaData = 0x0000, // This is not a resource file ContainsNoMetaData = 0x0001, // This is a resource file or other non-metadata-containing file } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/FunctionPointerType.cs ================================================ // // FunctionPointerType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Text; using Mono.Collections.Generic; using MD = Mono.Cecil.Metadata; namespace Mono.Cecil { public sealed class FunctionPointerType : TypeSpecification, IMethodSignature { readonly MethodReference function; public bool HasThis { get { return function.HasThis; } set { function.HasThis = value; } } public bool ExplicitThis { get { return function.ExplicitThis; } set { function.ExplicitThis = value; } } public MethodCallingConvention CallingConvention { get { return function.CallingConvention; } set { function.CallingConvention = value; } } public bool HasParameters { get { return function.HasParameters; } } public Collection Parameters { get { return function.Parameters; } } public TypeReference ReturnType { get { return function.MethodReturnType.ReturnType; } set { function.MethodReturnType.ReturnType = value; } } public MethodReturnType MethodReturnType { get { return function.MethodReturnType; } } public override string Name { get { return function.Name; } set { throw new InvalidOperationException (); } } public override string Namespace { get { return string.Empty; } set { throw new InvalidOperationException (); } } public override ModuleDefinition Module { get { return ReturnType.Module; } } public override IMetadataScope Scope { get { return function.ReturnType.Scope; } } public override bool IsFunctionPointer { get { return true; } } internal override bool ContainsGenericParameter { get { return function.ContainsGenericParameter; } } public override string FullName { get { var signature = new StringBuilder (); signature.Append (function.Name); signature.Append (" "); signature.Append (function.ReturnType.FullName); signature.Append (" *"); Mixin.MethodSignatureFullName (this,signature); return signature.ToString (); } } public FunctionPointerType () : base (null) { this.function = new MethodReference (); this.function.Name = "method"; this.etype = MD.ElementType.FnPtr; } public override TypeDefinition Resolve () { return null; } public override TypeReference GetElementType () { return this; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/GenericInstanceMethod.cs ================================================ // // GenericInstanceMethod.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Text; using Mono.Collections.Generic; namespace Mono.Cecil { public sealed class GenericInstanceMethod : MethodSpecification, IGenericInstance, IGenericContext { Collection arguments; public bool HasGenericArguments { get { return !Mixin.IsNullOrEmpty(arguments); } } public Collection GenericArguments { get { return arguments ?? (arguments = new Collection()); } } public override bool IsGenericInstance { get { return true; } } IGenericParameterProvider IGenericContext.Method { get { return ElementMethod; } } IGenericParameterProvider IGenericContext.Type { get { return ElementMethod.DeclaringType; } } internal override bool ContainsGenericParameter { get { return Mixin.ContainsGenericParameter(this) || base.ContainsGenericParameter; } } public override string FullName { get { var signature = new StringBuilder(); var method = this.ElementMethod; signature.Append(method.ReturnType.FullName) .Append(" ") .Append(method.DeclaringType.FullName) .Append("::") .Append(method.Name); Mixin.GenericInstanceFullName(this, signature); Mixin.MethodSignatureFullName(this, signature); return signature.ToString(); } } public GenericInstanceMethod(MethodReference method) : base(method) { } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/GenericInstanceType.cs ================================================ // // GenericInstanceType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Text; using Mono.Collections.Generic; using MD = Mono.Cecil.Metadata; namespace Mono.Cecil { public sealed class GenericInstanceType : TypeSpecification, IGenericInstance, IGenericContext { Collection arguments; public bool HasGenericArguments { get { return !Mixin.IsNullOrEmpty(arguments); } } public Collection GenericArguments { get { return arguments ?? (arguments = new Collection()); } } public override TypeReference DeclaringType { get { return ElementType.DeclaringType; } set { throw new NotSupportedException(); } } public override string FullName { get { var name = new StringBuilder(); name.Append(base.FullName); Mixin.GenericInstanceFullName(this, name); return name.ToString(); } } public override bool IsGenericInstance { get { return true; } } internal override bool ContainsGenericParameter { get { return Mixin.ContainsGenericParameter(this) || base.ContainsGenericParameter; } } IGenericParameterProvider IGenericContext.Type { get { return ElementType; } } public GenericInstanceType(TypeReference type) : base(type) { base.IsValueType = type.IsValueType; this.etype = MD.ElementType.GenericInst; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/GenericParameter.cs ================================================ // // GenericParameter.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Collections.Generic; using Mono.Cecil.Metadata; namespace Mono.Cecil { public sealed class GenericParameter : TypeReference, ICustomAttributeProvider { internal int position; internal GenericParameterType type; internal IGenericParameterProvider owner; ushort attributes; Collection constraints; Collection custom_attributes; public GenericParameterAttributes Attributes { get { return (GenericParameterAttributes) attributes; } set { attributes = (ushort) value; } } public int Position { get { return position; } } public GenericParameterType Type { get { return type; } } public IGenericParameterProvider Owner { get { return owner; } } public bool HasConstraints { get { if (constraints != null) return constraints.Count > 0; if (HasImage) return Module.Read (this, (generic_parameter, reader) => reader.HasGenericConstraints (generic_parameter)); return false; } } public Collection Constraints { get { if (constraints != null) return constraints; if (HasImage) return Module.Read (ref constraints, this, (generic_parameter, reader) => reader.ReadGenericConstraints (generic_parameter)); return constraints = new Collection (); } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return Mixin.GetHasCustomAttributes(this, Module); } } public Collection CustomAttributes { get { return custom_attributes ?? (Mixin.GetCustomAttributes(this, ref custom_attributes, Module)); } } public override IMetadataScope Scope { get { if (owner == null) return null; return owner.GenericParameterType == GenericParameterType.Method ? ((MethodReference) owner).DeclaringType.Scope : ((TypeReference) owner).Scope; } } public override ModuleDefinition Module { get { return module ?? owner.Module; } } public override string Name { get { if (!string.IsNullOrEmpty (base.Name)) return base.Name; return base.Name = (type == GenericParameterType.Method ? "!!" : "!") + position; } } public override string Namespace { get { return string.Empty; } set { throw new InvalidOperationException (); } } public override string FullName { get { return Name; } } public override bool IsGenericParameter { get { return true; } } internal override bool ContainsGenericParameter { get { return true; } } public override MetadataType MetadataType { get { return (MetadataType) etype; } } #region GenericParameterAttributes public bool IsNonVariant { get { return Mixin.GetMaskedAttributes(attributes,(ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.NonVariant); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.NonVariant, value); } } public bool IsCovariant { get { return Mixin.GetMaskedAttributes(attributes,(ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.Covariant); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.Covariant, value); } } public bool IsContravariant { get { return Mixin.GetMaskedAttributes(attributes,(ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.Contravariant); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.Contravariant, value); } } public bool HasReferenceTypeConstraint { get { return Mixin.GetAttributes(attributes,(ushort) GenericParameterAttributes.ReferenceTypeConstraint); } set { attributes =Mixin.SetAttributes(attributes,(ushort) GenericParameterAttributes.ReferenceTypeConstraint, value); } } public bool HasNotNullableValueTypeConstraint { get { return Mixin.GetAttributes(attributes,(ushort) GenericParameterAttributes.NotNullableValueTypeConstraint); } set { attributes =Mixin.SetAttributes(attributes,(ushort) GenericParameterAttributes.NotNullableValueTypeConstraint, value); } } public bool HasDefaultConstructorConstraint { get { return Mixin.GetAttributes(attributes,(ushort) GenericParameterAttributes.DefaultConstructorConstraint); } set { attributes =Mixin.SetAttributes(attributes,(ushort) GenericParameterAttributes.DefaultConstructorConstraint, value); } } #endregion public GenericParameter (IGenericParameterProvider owner) : this (string.Empty, owner) { } public GenericParameter (string name, IGenericParameterProvider owner) : base (string.Empty, name) { if (owner == null) throw new ArgumentNullException (); this.position = -1; this.owner = owner; this.type = owner.GenericParameterType; this.etype = ConvertGenericParameterType (this.type); } public GenericParameter (int position, GenericParameterType type, ModuleDefinition module) : base (string.Empty, string.Empty) { if (module == null) throw new ArgumentNullException (); this.position = position; this.type = type; this.etype = ConvertGenericParameterType (type); this.module = module; } static ElementType ConvertGenericParameterType (GenericParameterType type) { switch (type) { case GenericParameterType.Type: return ElementType.Var; case GenericParameterType.Method: return ElementType.MVar; } throw new ArgumentOutOfRangeException (); } public override TypeDefinition Resolve () { return null; } } sealed class GenericParameterCollection : Collection { readonly IGenericParameterProvider owner; internal GenericParameterCollection (IGenericParameterProvider owner) { this.owner = owner; } internal GenericParameterCollection (IGenericParameterProvider owner, int capacity) : base (capacity) { this.owner = owner; } protected override void OnAdd (GenericParameter item, int index) { UpdateGenericParameter (item, index); } protected override void OnInsert (GenericParameter item, int index) { UpdateGenericParameter (item, index); for (int i = index; i < size; i++) items[i].position = i + 1; } protected override void OnSet (GenericParameter item, int index) { UpdateGenericParameter (item, index); } void UpdateGenericParameter (GenericParameter item, int index) { item.owner = owner; item.position = index; item.type = owner.GenericParameterType; } protected override void OnRemove (GenericParameter item, int index) { item.owner = null; item.position = -1; item.type = GenericParameterType.Type; for (int i = index + 1; i < size; i++) items[i].position = i - 1; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/GenericParameterAttributes.cs ================================================ // // GenericParameterAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum GenericParameterAttributes : ushort { VarianceMask = 0x0003, NonVariant = 0x0000, Covariant = 0x0001, Contravariant = 0x0002, SpecialConstraintMask = 0x001c, ReferenceTypeConstraint = 0x0004, NotNullableValueTypeConstraint = 0x0008, DefaultConstructorConstraint = 0x0010 } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/IConstantProvider.cs ================================================ // // IConstantProvider.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public interface IConstantProvider : IMetadataTokenProvider { bool HasConstant { get; set; } object Constant { get; set; } } static partial class Mixin { internal static object NoValue = new object (); internal static object NotResolved = new object (); public static void ResolveConstant ( IConstantProvider self, ref object constant, ModuleDefinition module) { lock (module.SyncRoot) { if (constant != Mixin.NotResolved) return; if (Mixin.HasImage (module)) constant = module.Read (self, (provider, reader) => reader.ReadConstant (provider)); else constant = Mixin.NoValue; } } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/ICustomAttributeProvider.cs ================================================ // // ICustomAttributeProvider.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Collections.Generic; namespace Mono.Cecil { public interface ICustomAttributeProvider : IMetadataTokenProvider { Collection CustomAttributes { get; } bool HasCustomAttributes { get; } } static partial class Mixin { public static bool GetHasCustomAttributes( ICustomAttributeProvider self, ModuleDefinition module) { return Mixin.HasImage(module) && module.Read(self, (provider, reader) => reader.HasCustomAttributes(provider)); } public static Collection GetCustomAttributes( ICustomAttributeProvider self, ref Collection variable, ModuleDefinition module) { return Mixin.HasImage(module) ? module.Read(ref variable, self, (provider, reader) => reader.ReadCustomAttributes(provider)) : variable = new Collection(); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/IGenericInstance.cs ================================================ // // IGenericInstance.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System.Text; using Mono.Collections.Generic; namespace Mono.Cecil { public interface IGenericInstance : IMetadataTokenProvider { bool HasGenericArguments { get; } Collection GenericArguments { get; } } static partial class Mixin { public static bool ContainsGenericParameter (IGenericInstance self) { var arguments = self.GenericArguments; for (int i = 0; i < arguments.Count; i++) if (arguments [i].ContainsGenericParameter) return true; return false; } public static void GenericInstanceFullName (IGenericInstance self, StringBuilder builder) { builder.Append ("<"); var arguments = self.GenericArguments; for (int i = 0; i < arguments.Count; i++) { if (i > 0) builder.Append (","); builder.Append (arguments [i].FullName); } builder.Append (">"); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/IGenericParameterProvider.cs ================================================ // // IGenericParameterProvider.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using Mono.Collections.Generic; namespace Mono.Cecil { public interface IGenericParameterProvider : IMetadataTokenProvider { bool HasGenericParameters { get; } bool IsDefinition { get; } ModuleDefinition Module { get; } Collection GenericParameters { get; } GenericParameterType GenericParameterType { get; } } public enum GenericParameterType { Type, Method } interface IGenericContext { bool IsDefinition { get; } IGenericParameterProvider Type { get; } IGenericParameterProvider Method { get; } } static partial class Mixin { public static bool GetHasGenericParameters( IGenericParameterProvider self, ModuleDefinition module) { return Mixin.HasImage(module) && module.Read(self, (provider, reader) => reader.HasGenericParameters(provider)); } public static Collection GetGenericParameters( IGenericParameterProvider self, ref Collection collection, ModuleDefinition module) { return Mixin.HasImage(module) ? module.Read(ref collection, self, (provider, reader) => reader.ReadGenericParameters(provider)) : collection = new GenericParameterCollection(self); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/IMarshalInfoProvider.cs ================================================ // // IMarshalInfoProvider.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public interface IMarshalInfoProvider : IMetadataTokenProvider { bool HasMarshalInfo { get; } MarshalInfo MarshalInfo { get; set; } } static partial class Mixin { public static bool GetHasMarshalInfo( IMarshalInfoProvider self, ModuleDefinition module) { return Mixin.HasImage(module) && module.Read(self, (provider, reader) => reader.HasMarshalInfo(provider)); } public static MarshalInfo GetMarshalInfo( IMarshalInfoProvider self, ref MarshalInfo variable, ModuleDefinition module) { return Mixin.HasImage(module) ? module.Read(ref variable, self, (provider, reader) => reader.ReadMarshalInfo(provider)) : null; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/IMemberDefinition.cs ================================================ // // IMemberDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public interface IMemberDefinition : ICustomAttributeProvider { string Name { get; set; } string FullName { get; } bool IsSpecialName { get; set; } bool IsRuntimeSpecialName { get; set; } TypeDefinition DeclaringType { get; set; } } static partial class Mixin { public static bool GetAttributes(uint self, uint attributes) { return (self & attributes) != 0; } public static uint SetAttributes(uint self, uint attributes, bool value) { if (value) return self | attributes; return self & ~attributes; } public static bool GetMaskedAttributes(uint self, uint mask, uint attributes) { return (self & mask) == attributes; } public static uint SetMaskedAttributes(uint self, uint mask, uint attributes, bool value) { if (value) { self &= ~mask; return self | attributes; } return self & ~(mask & attributes); } public static bool GetAttributes(ushort self, ushort attributes) { return (self & attributes) != 0; } public static ushort SetAttributes(ushort self, ushort attributes, bool value) { if (value) return (ushort)(self | attributes); return (ushort)(self & ~attributes); } public static bool GetMaskedAttributes(ushort self, ushort mask, uint attributes) { return (self & mask) == attributes; } public static ushort SetMaskedAttributes(ushort self, ushort mask, uint attributes, bool value) { if (value) { self = (ushort)(self & ~mask); return (ushort)(self | attributes); } return (ushort)(self & ~(mask & attributes)); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/IMetadataScope.cs ================================================ // // IMetadataScope.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public enum MetadataScopeType { AssemblyNameReference, ModuleReference, ModuleDefinition, } public interface IMetadataScope : IMetadataTokenProvider { MetadataScopeType MetadataScopeType { get; } string Name { get; set; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/IMetadataTokenProvider.cs ================================================ // // IMetadataTokenProvider.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public interface IMetadataTokenProvider { MetadataToken MetadataToken { get; set; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/IMethodSignature.cs ================================================ // // IMethodSignature.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System.Text; using Mono.Collections.Generic; namespace Mono.Cecil { public interface IMethodSignature : IMetadataTokenProvider { bool HasThis { get; set; } bool ExplicitThis { get; set; } MethodCallingConvention CallingConvention { get; set; } bool HasParameters { get; } Collection Parameters { get; } TypeReference ReturnType { get; set; } MethodReturnType MethodReturnType { get; } } static partial class Mixin { public static bool HasImplicitThis (IMethodSignature self) { return self.HasThis && !self.ExplicitThis; } public static void MethodSignatureFullName (IMethodSignature self, StringBuilder builder) { builder.Append ("("); if (self.HasParameters) { var parameters = self.Parameters; for (int i = 0; i < parameters.Count; i++) { var parameter = parameters [i]; if (i > 0) builder.Append (","); if (parameter.ParameterType.IsSentinel) builder.Append ("...,"); builder.Append (parameter.ParameterType.FullName); } } builder.Append (")"); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/Import.cs ================================================ // // Import.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using SR = System.Reflection; using Mono.Cecil.Metadata; namespace Mono.Cecil { enum ImportGenericKind { Definition, Open, } class MetadataImporter { readonly ModuleDefinition module; public MetadataImporter(ModuleDefinition module) { this.module = module; } public TypeReference ImportType(TypeReference type, IGenericContext context) { if (Mixin.IsTypeSpecification(type)) return ImportTypeSpecification(type, context); var reference = new TypeReference( type.Namespace, type.Name, module, ImportScope(type.Scope), type.IsValueType); MetadataSystem.TryProcessPrimitiveTypeReference(reference); if (type.IsNested) reference.DeclaringType = ImportType(type.DeclaringType, context); if (type.HasGenericParameters) ImportGenericParameters(reference, type); return reference; } IMetadataScope ImportScope(IMetadataScope scope) { switch (scope.MetadataScopeType) { case MetadataScopeType.AssemblyNameReference: return ImportAssemblyName((AssemblyNameReference)scope); case MetadataScopeType.ModuleDefinition: return ImportAssemblyName(((ModuleDefinition)scope).Assembly.Name); case MetadataScopeType.ModuleReference: throw new NotImplementedException(); } throw new NotSupportedException(); } AssemblyNameReference ImportAssemblyName(AssemblyNameReference name) { AssemblyNameReference reference; if (TryGetAssemblyNameReference(name, out reference)) return reference; reference = new AssemblyNameReference(name.Name, name.Version) { Culture = name.Culture, HashAlgorithm = name.HashAlgorithm, }; var pk_token = !Mixin.IsNullOrEmpty(name.PublicKeyToken) ? new byte[name.PublicKeyToken.Length] : Empty.Array; if (pk_token.Length > 0) Buffer.BlockCopy(name.PublicKeyToken, 0, pk_token, 0, pk_token.Length); reference.PublicKeyToken = pk_token; module.AssemblyReferences.Add(reference); return reference; } bool TryGetAssemblyNameReference(AssemblyNameReference name_reference, out AssemblyNameReference assembly_reference) { var references = module.AssemblyReferences; for (int i = 0; i < references.Count; i++) { var reference = references[i]; if (name_reference.FullName != reference.FullName) // TODO compare field by field continue; assembly_reference = reference; return true; } assembly_reference = null; return false; } static void ImportGenericParameters(IGenericParameterProvider imported, IGenericParameterProvider original) { var parameters = original.GenericParameters; var imported_parameters = imported.GenericParameters; for (int i = 0; i < parameters.Count; i++) imported_parameters.Add(new GenericParameter(parameters[i].Name, imported)); } TypeReference ImportTypeSpecification(TypeReference type, IGenericContext context) { switch (type.etype) { case ElementType.SzArray: var vector = (ArrayType)type; return new ArrayType(ImportType(vector.ElementType, context)); case ElementType.Ptr: var pointer = (PointerType)type; return new PointerType(ImportType(pointer.ElementType, context)); case ElementType.ByRef: var byref = (ByReferenceType)type; return new ByReferenceType(ImportType(byref.ElementType, context)); case ElementType.Pinned: var pinned = (PinnedType)type; return new PinnedType(ImportType(pinned.ElementType, context)); case ElementType.Sentinel: var sentinel = (SentinelType)type; return new SentinelType(ImportType(sentinel.ElementType, context)); case ElementType.CModOpt: var modopt = (OptionalModifierType)type; return new OptionalModifierType( ImportType(modopt.ModifierType, context), ImportType(modopt.ElementType, context)); case ElementType.CModReqD: var modreq = (RequiredModifierType)type; return new RequiredModifierType( ImportType(modreq.ModifierType, context), ImportType(modreq.ElementType, context)); case ElementType.Array: var array = (ArrayType)type; var imported_array = new ArrayType(ImportType(array.ElementType, context)); if (array.IsVector) return imported_array; var dimensions = array.Dimensions; var imported_dimensions = imported_array.Dimensions; imported_dimensions.Clear(); for (int i = 0; i < dimensions.Count; i++) { var dimension = dimensions[i]; imported_dimensions.Add(new ArrayDimension(dimension.LowerBound, dimension.UpperBound)); } return imported_array; case ElementType.GenericInst: var instance = (GenericInstanceType)type; var element_type = ImportType(instance.ElementType, context); var imported_instance = new GenericInstanceType(element_type); var arguments = instance.GenericArguments; var imported_arguments = imported_instance.GenericArguments; for (int i = 0; i < arguments.Count; i++) imported_arguments.Add(ImportType(arguments[i], context)); return imported_instance; case ElementType.Var: if (context == null || context.Type == null) throw new InvalidOperationException(); return ((TypeReference)context.Type).GetElementType().GenericParameters[((GenericParameter)type).Position]; case ElementType.MVar: if (context == null || context.Method == null) throw new InvalidOperationException(); return context.Method.GenericParameters[((GenericParameter)type).Position]; } throw new NotSupportedException(type.etype.ToString()); } public FieldReference ImportField(FieldReference field, IGenericContext context) { var declaring_type = ImportType(field.DeclaringType, context); return new FieldReference { Name = field.Name, DeclaringType = declaring_type, FieldType = ImportType(field.FieldType, context ?? declaring_type), }; } public MethodReference ImportMethod(MethodReference method, IGenericContext context) { if (method.IsGenericInstance) return ImportMethodSpecification(method, context); var declaring_type = ImportType(method.DeclaringType, context); var reference = new MethodReference { Name = method.Name, HasThis = method.HasThis, ExplicitThis = method.ExplicitThis, DeclaringType = declaring_type, }; reference.CallingConvention = method.CallingConvention; if (method.HasGenericParameters) ImportGenericParameters(reference, method); reference.ReturnType = ImportType(method.ReturnType, context ?? reference); if (!method.HasParameters) return reference; var reference_parameters = reference.Parameters; var parameters = method.Parameters; for (int i = 0; i < parameters.Count; i++) reference_parameters.Add( new ParameterDefinition(ImportType(parameters[i].ParameterType, context ?? reference))); return reference; } MethodSpecification ImportMethodSpecification(MethodReference method, IGenericContext context) { if (!method.IsGenericInstance) throw new NotSupportedException(); var instance = (GenericInstanceMethod)method; var element_method = ImportMethod(instance.ElementMethod, context); var imported_instance = new GenericInstanceMethod(element_method); var arguments = instance.GenericArguments; var imported_arguments = imported_instance.GenericArguments; for (int i = 0; i < arguments.Count; i++) imported_arguments.Add(ImportType(arguments[i], context)); return imported_instance; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/LinkedResource.cs ================================================ // // LinkedResource.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public sealed class LinkedResource : Resource { internal byte [] hash; string file; public byte [] Hash { get { return hash; } } public string File { get { return file; } set { file = value; } } public override ResourceType ResourceType { get { return ResourceType.Linked; } } public LinkedResource (string name, ManifestResourceAttributes flags) : base (name, flags) { } public LinkedResource (string name, ManifestResourceAttributes flags, string file) : base (name, flags) { this.file = file; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/ManifestResourceAttributes.cs ================================================ // // ManifestResourceAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum ManifestResourceAttributes : uint { VisibilityMask = 0x0007, Public = 0x0001, // The resource is exported from the Assembly Private = 0x0002 // The resource is private to the Assembly } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/MarshalInfo.cs ================================================ // // MarshalInfo.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { public class MarshalInfo { internal NativeType native; public NativeType NativeType { get { return native; } set { native = value; } } public MarshalInfo (NativeType native) { this.native = native; } } public sealed class ArrayMarshalInfo : MarshalInfo { internal NativeType element_type; internal int size_parameter_index; internal int size; internal int size_parameter_multiplier; public NativeType ElementType { get { return element_type; } set { element_type = value; } } public int SizeParameterIndex { get { return size_parameter_index; } set { size_parameter_index = value; } } public int Size { get { return size; } set { size = value; } } public int SizeParameterMultiplier { get { return size_parameter_multiplier; } set { size_parameter_multiplier = value; } } public ArrayMarshalInfo () : base (NativeType.Array) { element_type = NativeType.None; size_parameter_index = -1; size = -1; size_parameter_multiplier = -1; } } public sealed class CustomMarshalInfo : MarshalInfo { internal Guid guid; internal string unmanaged_type; internal TypeReference managed_type; internal string cookie; public Guid Guid { get { return guid; } set { guid = value; } } public string UnmanagedType { get { return unmanaged_type; } set { unmanaged_type = value; } } public TypeReference ManagedType { get { return managed_type; } set { managed_type = value; } } public string Cookie { get { return cookie; } set { cookie = value; } } public CustomMarshalInfo () : base (NativeType.CustomMarshaler) { } } public sealed class SafeArrayMarshalInfo : MarshalInfo { internal VariantType element_type; public VariantType ElementType { get { return element_type; } set { element_type = value; } } public SafeArrayMarshalInfo () : base (NativeType.SafeArray) { element_type = VariantType.None; } } public sealed class FixedArrayMarshalInfo : MarshalInfo { internal NativeType element_type; internal int size; public NativeType ElementType { get { return element_type; } set { element_type = value; } } public int Size { get { return size; } set { size = value; } } public FixedArrayMarshalInfo () : base (NativeType.FixedArray) { element_type = NativeType.None; } } public sealed class FixedSysStringMarshalInfo : MarshalInfo { internal int size; public int Size { get { return size; } set { size = value; } } public FixedSysStringMarshalInfo () : base (NativeType.FixedSysString) { size = -1; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/MemberDefinitionCollection.cs ================================================ // // MemberDefinitionCollection.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Collections.Generic; namespace Mono.Cecil { class MemberDefinitionCollection : Collection where T : IMemberDefinition { TypeDefinition container; internal MemberDefinitionCollection (TypeDefinition container) { this.container = container; } internal MemberDefinitionCollection (TypeDefinition container, int capacity) : base (capacity) { this.container = container; } protected override void OnAdd (T item, int index) { Attach (item); } protected sealed override void OnSet (T item, int index) { Attach (item); } protected sealed override void OnInsert (T item, int index) { Attach (item); } protected sealed override void OnRemove (T item, int index) { Detach (item); } protected sealed override void OnClear () { foreach (var definition in this) Detach (definition); } void Attach (T element) { if (element.DeclaringType == container) return; if (element.DeclaringType != null) throw new ArgumentException ("Member already attached"); element.DeclaringType = this.container; } static void Detach (T element) { element.DeclaringType = null; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/MemberReference.cs ================================================ // // MemberReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public abstract class MemberReference : IMetadataTokenProvider { string name; TypeReference declaring_type; internal MetadataToken token; public virtual string Name { get { return name; } set { name = value; } } public abstract string FullName { get; } public virtual TypeReference DeclaringType { get { return declaring_type; } set { declaring_type = value; } } public MetadataToken MetadataToken { get { return token; } set { token = value; } } internal bool HasImage { get { var module = Module; if (module == null) return false; return module.HasImage; } } public virtual ModuleDefinition Module { get { return declaring_type != null ? declaring_type.Module : null; } } public virtual bool IsDefinition { get { return false; } } internal virtual bool ContainsGenericParameter { get { return declaring_type != null && declaring_type.ContainsGenericParameter; } } internal MemberReference () { } internal MemberReference (string name) { this.name = name ?? string.Empty; } internal string MemberFullName () { if (declaring_type == null) return name; return declaring_type.FullName + "::" + name; } public override string ToString () { return FullName; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/MetadataResolver.cs ================================================ // // MetadataResolver.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Collections.Generic; namespace Mono.Cecil { public interface IAssemblyResolver { AssemblyDefinition Resolve(AssemblyNameReference name); AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters); AssemblyDefinition Resolve(string fullName); AssemblyDefinition Resolve(string fullName, ReaderParameters parameters); event AssemblyResolveEventHandler ResolveFailure; } public interface IMetadataResolver { TypeDefinition Resolve(TypeReference type); FieldDefinition Resolve(FieldReference field); MethodDefinition Resolve(MethodReference method); } public class ResolutionException : Exception { readonly MemberReference member; public MemberReference Member { get { return member; } } public ResolutionException(MemberReference member) : base("Failed to resolve " + member.FullName) { this.member = member; } } public class MetadataResolver : IMetadataResolver { readonly IAssemblyResolver assembly_resolver; public IAssemblyResolver AssemblyResolver { get { return assembly_resolver; } } public MetadataResolver(IAssemblyResolver assemblyResolver) { if (assemblyResolver == null) throw new ArgumentNullException("assemblyResolver"); assembly_resolver = assemblyResolver; } public virtual TypeDefinition Resolve(TypeReference type) { if (type == null) throw new ArgumentNullException("type"); type = type.GetElementType(); var scope = type.Scope; switch (scope.MetadataScopeType) { case MetadataScopeType.AssemblyNameReference: var assembly = assembly_resolver.Resolve((AssemblyNameReference)scope); if (assembly == null) return null; return GetType(assembly.MainModule, type); case MetadataScopeType.ModuleDefinition: return GetType((ModuleDefinition)scope, type); case MetadataScopeType.ModuleReference: var modules = type.Module.Assembly.Modules; var module_ref = (ModuleReference)scope; for (int i = 0; i < modules.Count; i++) { var netmodule = modules[i]; if (netmodule.Name == module_ref.Name) return GetType(netmodule, type); } break; } throw new NotSupportedException(); } static TypeDefinition GetType(ModuleDefinition module, TypeReference reference) { var type = GetTypeDefinition(module, reference); if (type != null) return type; if (!module.HasExportedTypes) return null; var exported_types = module.ExportedTypes; for (int i = 0; i < exported_types.Count; i++) { var exported_type = exported_types[i]; if (exported_type.Name != reference.Name) continue; if (exported_type.Namespace != reference.Namespace) continue; return exported_type.Resolve(); } return null; } static TypeDefinition GetTypeDefinition(ModuleDefinition module, TypeReference type) { if (!type.IsNested) return module.GetType(type.Namespace, type.Name); var declaring_type = type.DeclaringType.Resolve(); if (declaring_type == null) return null; return Mixin.GetNestedType(declaring_type, type.Name); } public virtual FieldDefinition Resolve(FieldReference field) { if (field == null) throw new ArgumentNullException("field"); var type = Resolve(field.DeclaringType); if (type == null) return null; if (!type.HasFields) return null; return GetField(type, field); } FieldDefinition GetField(TypeDefinition type, FieldReference reference) { while (type != null) { var field = GetField(type.Fields, reference); if (field != null) return field; if (type.BaseType == null) return null; type = Resolve(type.BaseType); } return null; } static FieldDefinition GetField(Collection fields, FieldReference reference) { for (int i = 0; i < fields.Count; i++) { var field = fields[i]; if (field.Name != reference.Name) continue; if (!AreSame(field.FieldType, reference.FieldType)) continue; return field; } return null; } public virtual MethodDefinition Resolve(MethodReference method) { if (method == null) throw new ArgumentNullException("method"); var type = Resolve(method.DeclaringType); if (type == null) return null; method = method.GetElementMethod(); if (!type.HasMethods) return null; return GetMethod(type, method); } MethodDefinition GetMethod(TypeDefinition type, MethodReference reference) { while (type != null) { var method = GetMethod(type.Methods, reference); if (method != null) return method; if (type.BaseType == null) return null; type = Resolve(type.BaseType); } return null; } public static MethodDefinition GetMethod(Collection methods, MethodReference reference) { for (int i = 0; i < methods.Count; i++) { var method = methods[i]; if (method.Name != reference.Name) continue; if (method.HasGenericParameters != reference.HasGenericParameters) continue; if (method.HasGenericParameters && method.GenericParameters.Count != reference.GenericParameters.Count) continue; if (!AreSame(method.ReturnType, reference.ReturnType)) continue; if (method.HasParameters != reference.HasParameters) continue; if (!method.HasParameters && !reference.HasParameters) return method; if (!AreSame(method.Parameters, reference.Parameters)) continue; return method; } return null; } static bool AreSame(Collection a, Collection b) { var count = a.Count; if (count != b.Count) return false; if (count == 0) return true; for (int i = 0; i < count; i++) if (!AreSame(a[i].ParameterType, b[i].ParameterType)) return false; return true; } static bool AreSame(TypeSpecification a, TypeSpecification b) { if (!AreSame(a.ElementType, b.ElementType)) return false; if (a.IsGenericInstance) return AreSame((GenericInstanceType)a, (GenericInstanceType)b); if (a.IsRequiredModifier || a.IsOptionalModifier) return AreSame((IModifierType)a, (IModifierType)b); if (a.IsArray) return AreSame((ArrayType)a, (ArrayType)b); return true; } static bool AreSame(ArrayType a, ArrayType b) { if (a.Rank != b.Rank) return false; // TODO: dimensions return true; } static bool AreSame(IModifierType a, IModifierType b) { return AreSame(a.ModifierType, b.ModifierType); } static bool AreSame(GenericInstanceType a, GenericInstanceType b) { if (a.GenericArguments.Count != b.GenericArguments.Count) return false; for (int i = 0; i < a.GenericArguments.Count; i++) if (!AreSame(a.GenericArguments[i], b.GenericArguments[i])) return false; return true; } static bool AreSame(GenericParameter a, GenericParameter b) { return a.Position == b.Position; } static bool AreSame(TypeReference a, TypeReference b) { if (ReferenceEquals(a, b)) return true; if (a == null || b == null) return false; if (a.etype != b.etype) return false; if (a.IsGenericParameter) return AreSame((GenericParameter)a, (GenericParameter)b); if (Mixin.IsTypeSpecification(a)) return AreSame((TypeSpecification)a, (TypeSpecification)b); if (a.Name != b.Name || a.Namespace != b.Namespace) return false; //TODO: check scope return AreSame(a.DeclaringType, b.DeclaringType); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/MetadataSystem.cs ================================================ // // MetadataSystem.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using Mono.Cecil.Metadata; namespace Mono.Cecil { struct Range { public uint Start; public uint Length; public Range (uint index, uint length) { this.Start = index; this.Length = length; } } sealed class MetadataSystem { internal AssemblyNameReference [] AssemblyReferences; internal ModuleReference [] ModuleReferences; internal TypeDefinition [] Types; internal TypeReference [] TypeReferences; internal FieldDefinition [] Fields; internal MethodDefinition [] Methods; internal MemberReference [] MemberReferences; internal Dictionary NestedTypes; internal Dictionary ReverseNestedTypes; internal Dictionary Interfaces; internal Dictionary> ClassLayouts; internal Dictionary FieldLayouts; internal Dictionary FieldRVAs; internal Dictionary FieldMarshals; internal Dictionary> Constants; internal Dictionary Overrides; internal Dictionary CustomAttributes; internal Dictionary SecurityDeclarations; internal Dictionary Events; internal Dictionary Properties; internal Dictionary> Semantics; internal Dictionary> PInvokes; internal Dictionary GenericParameters; internal Dictionary GenericConstraints; static Dictionary> primitive_value_types; static void InitializePrimitives () { primitive_value_types = new Dictionary> (18, StringComparer.Ordinal) { { "Void", new Row (ElementType.Void, false) }, { "Boolean", new Row (ElementType.Boolean, true) }, { "Char", new Row (ElementType.Char, true) }, { "SByte", new Row (ElementType.I1, true) }, { "Byte", new Row (ElementType.U1, true) }, { "Int16", new Row (ElementType.I2, true) }, { "UInt16", new Row (ElementType.U2, true) }, { "Int32", new Row (ElementType.I4, true) }, { "UInt32", new Row (ElementType.U4, true) }, { "Int64", new Row (ElementType.I8, true) }, { "UInt64", new Row (ElementType.U8, true) }, { "Single", new Row (ElementType.R4, true) }, { "Double", new Row (ElementType.R8, true) }, { "String", new Row (ElementType.String, false) }, { "TypedReference", new Row (ElementType.TypedByRef, false) }, { "IntPtr", new Row (ElementType.I, true) }, { "UIntPtr", new Row (ElementType.U, true) }, { "Object", new Row (ElementType.Object, false) }, }; } public static void TryProcessPrimitiveTypeReference (TypeReference type) { if (type.Namespace != "System") return; var scope = type.scope; if (scope == null || scope.MetadataScopeType != MetadataScopeType.AssemblyNameReference) return; Row primitive_data; if (!TryGetPrimitiveData (type, out primitive_data)) return; type.etype = primitive_data.Col1; type.IsValueType = primitive_data.Col2; } public static bool TryGetPrimitiveElementType (TypeDefinition type, out ElementType etype) { etype = ElementType.None; if (type.Namespace != "System") return false; Row primitive_data; if (TryGetPrimitiveData (type, out primitive_data) &&Mixin .IsPrimitive (primitive_data.Col1)) { etype = primitive_data.Col1; return true; } return false; } static bool TryGetPrimitiveData (TypeReference type, out Row primitive_data) { if (primitive_value_types == null) InitializePrimitives (); return primitive_value_types.TryGetValue (type.Name, out primitive_data); } public void Clear () { if (NestedTypes != null) NestedTypes.Clear (); if (ReverseNestedTypes != null) ReverseNestedTypes.Clear (); if (Interfaces != null) Interfaces.Clear (); if (ClassLayouts != null) ClassLayouts.Clear (); if (FieldLayouts != null) FieldLayouts.Clear (); if (FieldRVAs != null) FieldRVAs.Clear (); if (FieldMarshals != null) FieldMarshals.Clear (); if (Constants != null) Constants.Clear (); if (Overrides != null) Overrides.Clear (); if (CustomAttributes != null) CustomAttributes.Clear (); if (SecurityDeclarations != null) SecurityDeclarations.Clear (); if (Events != null) Events.Clear (); if (Properties != null) Properties.Clear (); if (Semantics != null) Semantics.Clear (); if (PInvokes != null) PInvokes.Clear (); if (GenericParameters != null) GenericParameters.Clear (); if (GenericConstraints != null) GenericConstraints.Clear (); } public TypeDefinition GetTypeDefinition (uint rid) { if (rid < 1 || rid > Types.Length) return null; return Types [rid - 1]; } public void AddTypeDefinition (TypeDefinition type) { Types [type.token.RID - 1] = type; } public TypeReference GetTypeReference (uint rid) { if (rid < 1 || rid > TypeReferences.Length) return null; return TypeReferences [rid - 1]; } public void AddTypeReference (TypeReference type) { TypeReferences [type.token.RID - 1] = type; } public FieldDefinition GetFieldDefinition (uint rid) { if (rid < 1 || rid > Fields.Length) return null; return Fields [rid - 1]; } public void AddFieldDefinition (FieldDefinition field) { Fields [field.token.RID - 1] = field; } public MethodDefinition GetMethodDefinition (uint rid) { if (rid < 1 || rid > Methods.Length) return null; return Methods [rid - 1]; } public void AddMethodDefinition (MethodDefinition method) { Methods [method.token.RID - 1] = method; } public MemberReference GetMemberReference (uint rid) { if (rid < 1 || rid > MemberReferences.Length) return null; return MemberReferences [rid - 1]; } public void AddMemberReference (MemberReference member) { MemberReferences [member.token.RID - 1] = member; } public bool TryGetNestedTypeMapping (TypeDefinition type, out uint [] mapping) { return NestedTypes.TryGetValue (type.token.RID, out mapping); } public void SetNestedTypeMapping (uint type_rid, uint [] mapping) { NestedTypes [type_rid] = mapping; } public void RemoveNestedTypeMapping (TypeDefinition type) { NestedTypes.Remove (type.token.RID); } public bool TryGetReverseNestedTypeMapping (TypeDefinition type, out uint declaring) { return ReverseNestedTypes.TryGetValue (type.token.RID, out declaring); } public void SetReverseNestedTypeMapping (uint nested, uint declaring) { ReverseNestedTypes.Add (nested, declaring); } public void RemoveReverseNestedTypeMapping (TypeDefinition type) { ReverseNestedTypes.Remove (type.token.RID); } public bool TryGetInterfaceMapping (TypeDefinition type, out MetadataToken [] mapping) { return Interfaces.TryGetValue (type.token.RID, out mapping); } public void SetInterfaceMapping (uint type_rid, MetadataToken [] mapping) { Interfaces [type_rid] = mapping; } public void RemoveInterfaceMapping (TypeDefinition type) { Interfaces.Remove (type.token.RID); } public void AddPropertiesRange (uint type_rid, Range range) { Properties.Add (type_rid, range); } public bool TryGetPropertiesRange (TypeDefinition type, out Range range) { return Properties.TryGetValue (type.token.RID, out range); } public void RemovePropertiesRange (TypeDefinition type) { Properties.Remove (type.token.RID); } public void AddEventsRange (uint type_rid, Range range) { Events.Add (type_rid, range); } public bool TryGetEventsRange (TypeDefinition type, out Range range) { return Events.TryGetValue (type.token.RID, out range); } public void RemoveEventsRange (TypeDefinition type) { Events.Remove (type.token.RID); } public bool TryGetGenericParameterRange (IGenericParameterProvider owner, out Range range) { return GenericParameters.TryGetValue (owner.MetadataToken, out range); } public void RemoveGenericParameterRange (IGenericParameterProvider owner) { GenericParameters.Remove (owner.MetadataToken); } public bool TryGetCustomAttributeRange (ICustomAttributeProvider owner, out Range range) { return CustomAttributes.TryGetValue (owner.MetadataToken, out range); } public void RemoveCustomAttributeRange (ICustomAttributeProvider owner) { CustomAttributes.Remove (owner.MetadataToken); } public bool TryGetSecurityDeclarationRange (ISecurityDeclarationProvider owner, out Range range) { return SecurityDeclarations.TryGetValue (owner.MetadataToken, out range); } public void RemoveSecurityDeclarationRange (ISecurityDeclarationProvider owner) { SecurityDeclarations.Remove (owner.MetadataToken); } public bool TryGetGenericConstraintMapping (GenericParameter generic_parameter, out MetadataToken [] mapping) { return GenericConstraints.TryGetValue (generic_parameter.token.RID, out mapping); } public void SetGenericConstraintMapping (uint gp_rid, MetadataToken [] mapping) { GenericConstraints [gp_rid] = mapping; } public void RemoveGenericConstraintMapping (GenericParameter generic_parameter) { GenericConstraints.Remove (generic_parameter.token.RID); } public bool TryGetOverrideMapping (MethodDefinition method, out MetadataToken [] mapping) { return Overrides.TryGetValue (method.token.RID, out mapping); } public void SetOverrideMapping (uint rid, MetadataToken [] mapping) { Overrides [rid] = mapping; } public void RemoveOverrideMapping (MethodDefinition method) { Overrides.Remove (method.token.RID); } public TypeDefinition GetFieldDeclaringType (uint field_rid) { return BinaryRangeSearch (Types, field_rid, true); } public TypeDefinition GetMethodDeclaringType (uint method_rid) { return BinaryRangeSearch (Types, method_rid, false); } static TypeDefinition BinaryRangeSearch (TypeDefinition [] types, uint rid, bool field) { int min = 0; int max = types.Length - 1; while (min <= max) { int mid = min + ((max - min) / 2); var type = types [mid]; var range = field ? type.fields_range : type.methods_range; if (rid < range.Start) max = mid - 1; else if (rid >= range.Start + range.Length) min = mid + 1; else return type; } return null; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/MethodAttributes.cs ================================================ // // MethodAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum MethodAttributes : ushort { MemberAccessMask = 0x0007, CompilerControlled = 0x0000, // Member not referenceable Private = 0x0001, // Accessible only by the parent type FamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly Assembly = 0x0003, // Accessibly by anyone in the Assembly Family = 0x0004, // Accessible only by type and sub-types FamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly Public = 0x0006, // Accessibly by anyone who has visibility to this scope Static = 0x0010, // Defined on type, else per instance Final = 0x0020, // Method may not be overridden Virtual = 0x0040, // Method is virtual HideBySig = 0x0080, // Method hides by name+sig, else just by name VtableLayoutMask = 0x0100, // Use this mask to retrieve vtable attributes ReuseSlot = 0x0000, // Method reuses existing slot in vtable NewSlot = 0x0100, // Method always gets a new slot in the vtable CheckAccessOnOverride = 0x0200, // Method can only be overriden if also accessible Abstract = 0x0400, // Method does not provide an implementation SpecialName = 0x0800, // Method is special // Interop Attributes PInvokeImpl = 0x2000, // Implementation is forwarded through PInvoke UnmanagedExport = 0x0008, // Reserved: shall be zero for conforming implementations // Additional flags RTSpecialName = 0x1000, // CLI provides 'special' behavior, depending upon the name of the method HasSecurity = 0x4000, // Method has security associate with it RequireSecObject = 0x8000 // Method calls another method containing security code } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/MethodCallingConvention.cs ================================================ // // MethodCallingConvention.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public enum MethodCallingConvention : byte { Default = 0x0, C = 0x1, StdCall = 0x2, ThisCall = 0x3, FastCall = 0x4, VarArg = 0x5, Generic = 0x10, } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/MethodDefinition.cs ================================================ // // MethodDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using Mono.Cecil.Cil; using Mono.Collections.Generic; using RVA = System.UInt32; namespace Mono.Cecil { public sealed class MethodDefinition : MethodReference, IMemberDefinition, ISecurityDeclarationProvider { ushort attributes; ushort impl_attributes; internal volatile bool sem_attrs_ready; internal MethodSemanticsAttributes sem_attrs; Collection custom_attributes; Collection security_declarations; internal RVA rva; internal PInvokeInfo pinvoke; Collection overrides; internal MethodBody body; public MethodAttributes Attributes { get { return (MethodAttributes)attributes; } set { attributes = (ushort)value; } } public MethodImplAttributes ImplAttributes { get { return (MethodImplAttributes)impl_attributes; } set { impl_attributes = (ushort)value; } } public MethodSemanticsAttributes SemanticsAttributes { get { if (sem_attrs_ready) return sem_attrs; if (HasImage) { ReadSemantics(); return sem_attrs; } sem_attrs = MethodSemanticsAttributes.None; sem_attrs_ready = true; return sem_attrs; } set { sem_attrs = value; } } internal void ReadSemantics() { if (sem_attrs_ready) return; var module = this.Module; if (module == null) return; if (!module.HasImage) return; module.Read(this, (method, reader) => reader.ReadAllSemantics(method)); } public bool HasSecurityDeclarations { get { if (security_declarations != null) return security_declarations.Count > 0; return Mixin.GetHasSecurityDeclarations(this, Module); } } public Collection SecurityDeclarations { get { return security_declarations ?? (Mixin.GetSecurityDeclarations(this, ref security_declarations, Module)); } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return Mixin.GetHasCustomAttributes(this, Module); } } public Collection CustomAttributes { get { return custom_attributes ?? (Mixin.GetCustomAttributes(this, ref custom_attributes, Module)); } } public int RVA { get { return (int)rva; } } public bool HasBody { get { return (attributes & (ushort)MethodAttributes.Abstract) == 0 && (attributes & (ushort)MethodAttributes.PInvokeImpl) == 0 && (impl_attributes & (ushort)MethodImplAttributes.InternalCall) == 0 && (impl_attributes & (ushort)MethodImplAttributes.Native) == 0 && (impl_attributes & (ushort)MethodImplAttributes.Unmanaged) == 0 && (impl_attributes & (ushort)MethodImplAttributes.Runtime) == 0; } } public MethodBody Body { get { MethodBody localBody = this.body; if (localBody != null) return localBody; if (!HasBody) return null; if (HasImage && rva != 0) return Module.Read(ref body, this, (method, reader) => reader.ReadMethodBody(method)); return body = new MethodBody(this); } set { // we reset Body to null in ILSpy to save memory; so we need that operation to be thread-safe lock (Module.SyncRoot) { body = value; } } } public bool HasPInvokeInfo { get { if (pinvoke != null) return true; return IsPInvokeImpl; } } public PInvokeInfo PInvokeInfo { get { if (pinvoke != null) return pinvoke; if (HasImage && IsPInvokeImpl) return Module.Read(ref pinvoke, this, (method, reader) => reader.ReadPInvokeInfo(method)); return null; } set { IsPInvokeImpl = true; pinvoke = value; } } public bool HasOverrides { get { if (overrides != null) return overrides.Count > 0; if (HasImage) return Module.Read(this, (method, reader) => reader.HasOverrides(method)); return false; } } public Collection Overrides { get { if (overrides != null) return overrides; if (HasImage) return Module.Read(ref overrides, this, (method, reader) => reader.ReadOverrides(method)); return overrides = new Collection(); } } public override bool HasGenericParameters { get { if (generic_parameters != null) return generic_parameters.Count > 0; return Mixin.GetHasGenericParameters(this, Module); } } public override Collection GenericParameters { get { return generic_parameters ?? (Mixin.GetGenericParameters(this, ref generic_parameters, Module)); } } #region MethodAttributes public bool IsCompilerControlled { get { return Mixin.GetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.CompilerControlled); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.CompilerControlled, value); } } public bool IsPrivate { get { return Mixin.GetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Private); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Private, value); } } public bool IsFamilyAndAssembly { get { return Mixin.GetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.FamANDAssem); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.FamANDAssem, value); } } public bool IsAssembly { get { return Mixin.GetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Assembly); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Assembly, value); } } public bool IsFamily { get { return Mixin.GetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Family); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Family, value); } } public bool IsFamilyOrAssembly { get { return Mixin.GetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.FamORAssem); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.FamORAssem, value); } } public bool IsPublic { get { return Mixin.GetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Public); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Public, value); } } public bool IsStatic { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.Static); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.Static, value); } } public bool IsFinal { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.Final); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.Final, value); } } public bool IsVirtual { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.Virtual); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.Virtual, value); } } public bool IsHideBySig { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.HideBySig); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.HideBySig, value); } } public bool IsReuseSlot { get { return Mixin.GetMaskedAttributes(attributes,(ushort)MethodAttributes.VtableLayoutMask, (ushort)MethodAttributes.ReuseSlot); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort)MethodAttributes.VtableLayoutMask, (ushort)MethodAttributes.ReuseSlot, value); } } public bool IsNewSlot { get { return Mixin.GetMaskedAttributes(attributes,(ushort)MethodAttributes.VtableLayoutMask, (ushort)MethodAttributes.NewSlot); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort)MethodAttributes.VtableLayoutMask, (ushort)MethodAttributes.NewSlot, value); } } public bool IsCheckAccessOnOverride { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.CheckAccessOnOverride); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.CheckAccessOnOverride, value); } } public bool IsAbstract { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.Abstract); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.Abstract, value); } } public bool IsSpecialName { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.SpecialName); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.SpecialName, value); } } public bool IsPInvokeImpl { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.PInvokeImpl); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.PInvokeImpl, value); } } public bool IsUnmanagedExport { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.UnmanagedExport); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.UnmanagedExport, value); } } public bool IsRuntimeSpecialName { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.RTSpecialName); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.RTSpecialName, value); } } public bool HasSecurity { get { return Mixin.GetAttributes(attributes,(ushort)MethodAttributes.HasSecurity); } set { attributes =Mixin.SetAttributes(attributes,(ushort)MethodAttributes.HasSecurity, value); } } #endregion #region MethodImplAttributes public bool IsIL { get { return Mixin.GetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.CodeTypeMask, (ushort)MethodImplAttributes.IL); } set { impl_attributes = Mixin.SetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.CodeTypeMask, (ushort)MethodImplAttributes.IL, value); } } public bool IsNative { get { return Mixin.GetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.CodeTypeMask, (ushort)MethodImplAttributes.Native); } set { impl_attributes = Mixin.SetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.CodeTypeMask, (ushort)MethodImplAttributes.Native, value); } } public bool IsRuntime { get { return Mixin.GetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.CodeTypeMask, (ushort)MethodImplAttributes.Runtime); } set { impl_attributes = Mixin.SetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.CodeTypeMask, (ushort)MethodImplAttributes.Runtime, value); } } public bool IsUnmanaged { get { return Mixin.GetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.ManagedMask, (ushort)MethodImplAttributes.Unmanaged); } set { impl_attributes = Mixin.SetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.ManagedMask, (ushort)MethodImplAttributes.Unmanaged, value); } } public bool IsManaged { get { return Mixin.GetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.ManagedMask, (ushort)MethodImplAttributes.Managed); } set { impl_attributes = Mixin.SetMaskedAttributes(impl_attributes,(ushort)MethodImplAttributes.ManagedMask, (ushort)MethodImplAttributes.Managed, value); } } public bool IsForwardRef { get { return Mixin.GetAttributes(impl_attributes, (ushort)MethodImplAttributes.ForwardRef); } set { impl_attributes = Mixin.SetAttributes(impl_attributes,(ushort)MethodImplAttributes.ForwardRef, value); } } public bool IsPreserveSig { get { return Mixin.GetAttributes(impl_attributes, (ushort)MethodImplAttributes.PreserveSig); } set { impl_attributes = Mixin.SetAttributes(impl_attributes,(ushort)MethodImplAttributes.PreserveSig, value); } } public bool IsInternalCall { get { return Mixin.GetAttributes(impl_attributes, (ushort)MethodImplAttributes.InternalCall); } set { impl_attributes = Mixin.SetAttributes(impl_attributes,(ushort)MethodImplAttributes.InternalCall, value); } } public bool IsSynchronized { get { return Mixin.GetAttributes(impl_attributes, (ushort)MethodImplAttributes.Synchronized); } set { impl_attributes = Mixin.SetAttributes(impl_attributes,(ushort)MethodImplAttributes.Synchronized, value); } } public bool NoInlining { get { return Mixin.GetAttributes(impl_attributes, (ushort)MethodImplAttributes.NoInlining); } set { impl_attributes = Mixin.SetAttributes(impl_attributes,(ushort)MethodImplAttributes.NoInlining, value); } } public bool NoOptimization { get { return Mixin.GetAttributes(impl_attributes, (ushort)MethodImplAttributes.NoOptimization); } set { impl_attributes = Mixin.SetAttributes(impl_attributes,(ushort)MethodImplAttributes.NoOptimization, value); } } #endregion #region MethodSemanticsAttributes public bool IsSetter { get { return Mixin.GetSemantics(this, MethodSemanticsAttributes.Setter); } set { Mixin.SetSemantics(this, MethodSemanticsAttributes.Setter, value); } } public bool IsGetter { get { return Mixin.GetSemantics(this, MethodSemanticsAttributes.Getter); } set { Mixin.SetSemantics(this, MethodSemanticsAttributes.Getter, value); } } public bool IsOther { get { return Mixin.GetSemantics(this, MethodSemanticsAttributes.Other); } set { Mixin.SetSemantics(this, MethodSemanticsAttributes.Other, value); } } public bool IsAddOn { get { return Mixin.GetSemantics(this, MethodSemanticsAttributes.AddOn); } set { Mixin.SetSemantics(this, MethodSemanticsAttributes.AddOn, value); } } public bool IsRemoveOn { get { return Mixin.GetSemantics(this, MethodSemanticsAttributes.RemoveOn); } set { Mixin.SetSemantics(this, MethodSemanticsAttributes.RemoveOn, value); } } public bool IsFire { get { return Mixin.GetSemantics(this, MethodSemanticsAttributes.Fire); } set { Mixin.SetSemantics(this, MethodSemanticsAttributes.Fire, value); } } #endregion public new TypeDefinition DeclaringType { get { return (TypeDefinition)base.DeclaringType; } set { base.DeclaringType = value; } } public bool IsConstructor { get { return this.IsRuntimeSpecialName && this.IsSpecialName && (this.Name == ".cctor" || this.Name == ".ctor"); } } public override bool IsDefinition { get { return true; } } internal MethodDefinition() { this.token = new MetadataToken(TokenType.Method); } public MethodDefinition(string name, MethodAttributes attributes, TypeReference returnType) : base(name, returnType) { this.attributes = (ushort)attributes; this.HasThis = !this.IsStatic; this.token = new MetadataToken(TokenType.Method); } public override MethodDefinition Resolve() { return this; } } static partial class Mixin { public static ParameterDefinition GetParameter(MethodBody self, int index) { var method = self.method; if (method.HasThis) { if (index == 0) return self.ThisParameter; index--; } var parameters = method.Parameters; if (index < 0 || index >= parameters.size) return null; return parameters[index]; } public static VariableDefinition GetVariable(MethodBody self, int index) { var variables = self.Variables; if (index < 0 || index >= variables.size) return null; return variables[index]; } public static bool GetSemantics(MethodDefinition self, MethodSemanticsAttributes semantics) { return (self.SemanticsAttributes & semantics) != 0; } public static void SetSemantics(MethodDefinition self, MethodSemanticsAttributes semantics, bool value) { if (value) self.SemanticsAttributes |= semantics; else self.SemanticsAttributes &= ~semantics; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/MethodImplAttributes.cs ================================================ // // MethodImplAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum MethodImplAttributes : ushort { CodeTypeMask = 0x0003, IL = 0x0000, // Method impl is CIL Native = 0x0001, // Method impl is native OPTIL = 0x0002, // Reserved: shall be zero in conforming implementations Runtime = 0x0003, // Method impl is provided by the runtime ManagedMask = 0x0004, // Flags specifying whether the code is managed or unmanaged Unmanaged = 0x0004, // Method impl is unmanaged, otherwise managed Managed = 0x0000, // Method impl is managed // Implementation info and interop ForwardRef = 0x0010, // Indicates method is defined; used primarily in merge scenarios PreserveSig = 0x0080, // Reserved: conforming implementations may ignore InternalCall = 0x1000, // Reserved: shall be zero in conforming implementations Synchronized = 0x0020, // Method is single threaded through the body NoOptimization = 0x0040, // Method is not optimized by the JIT. NoInlining = 0x0008, // Method may not be inlined } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/MethodReference.cs ================================================ // // MethodReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Text; using Mono.Collections.Generic; namespace Mono.Cecil { public class MethodReference : MemberReference, IMethodSignature, IGenericParameterProvider, IGenericContext { int hashCode = -1; static int instance_id; internal ParameterDefinitionCollection parameters; MethodReturnType return_type; bool has_this; bool explicit_this; MethodCallingConvention calling_convention; internal Collection generic_parameters; public virtual bool HasThis { get { return has_this; } set { has_this = value; } } public virtual bool ExplicitThis { get { return explicit_this; } set { explicit_this = value; } } public virtual MethodCallingConvention CallingConvention { get { return calling_convention; } set { calling_convention = value; } } public virtual bool HasParameters { get { return !Mixin.IsNullOrEmpty(parameters); } } public virtual Collection Parameters { get { if (parameters == null) parameters = new ParameterDefinitionCollection(this); return parameters; } } IGenericParameterProvider IGenericContext.Type { get { var declaring_type = this.DeclaringType; var instance = declaring_type as GenericInstanceType; if (instance != null) return instance.ElementType; return declaring_type; } } IGenericParameterProvider IGenericContext.Method { get { return this; } } GenericParameterType IGenericParameterProvider.GenericParameterType { get { return GenericParameterType.Method; } } public virtual bool HasGenericParameters { get { return !Mixin.IsNullOrEmpty(generic_parameters); } } public virtual Collection GenericParameters { get { if (generic_parameters != null) return generic_parameters; return generic_parameters = new GenericParameterCollection(this); } } public TypeReference ReturnType { get { var return_type = MethodReturnType; return return_type != null ? return_type.ReturnType : null; } set { var return_type = MethodReturnType; if (return_type != null) return_type.ReturnType = value; } } public virtual MethodReturnType MethodReturnType { get { return return_type; } set { return_type = value; } } public override string FullName { get { var builder = new StringBuilder(); builder.Append(ReturnType.FullName) .Append(" ") .Append(MemberFullName()); Mixin.MethodSignatureFullName(this, builder); return builder.ToString(); } } public override int GetHashCode() { if (hashCode == -1) hashCode = System.Threading.Interlocked.Add(ref instance_id, 1); return hashCode; } public virtual bool IsGenericInstance { get { return false; } } internal override bool ContainsGenericParameter { get { if (this.ReturnType.ContainsGenericParameter || base.ContainsGenericParameter) return true; var parameters = this.Parameters; for (int i = 0; i < parameters.Count; i++) if (parameters[i].ParameterType.ContainsGenericParameter) return true; return false; } } internal MethodReference() { this.return_type = new MethodReturnType(this); this.token = new MetadataToken(TokenType.MemberRef); } public MethodReference(string name, TypeReference returnType) : base(name) { if (returnType == null) throw new ArgumentNullException("returnType"); this.return_type = new MethodReturnType(this); this.return_type.ReturnType = returnType; this.token = new MetadataToken(TokenType.MemberRef); } public MethodReference(string name, TypeReference returnType, TypeReference declaringType) : this(name, returnType) { if (declaringType == null) throw new ArgumentNullException("declaringType"); this.DeclaringType = declaringType; } public virtual MethodReference GetElementMethod() { return this; } public virtual MethodDefinition Resolve() { var module = this.Module; if (module == null) throw new NotSupportedException(); return module.Resolve(this); } } static partial class Mixin { public static bool IsVarArg(IMethodSignature self) { return (self.CallingConvention & MethodCallingConvention.VarArg) != 0; } public static int GetSentinelPosition(IMethodSignature self) { if (!self.HasParameters) return -1; var parameters = self.Parameters; for (int i = 0; i < parameters.Count; i++) if (parameters[i].ParameterType.IsSentinel) return i; return -1; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/MethodReturnType.cs ================================================ // // MethodReturnType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System.Threading; using Mono.Collections.Generic; namespace Mono.Cecil { public sealed class MethodReturnType : IConstantProvider, ICustomAttributeProvider, IMarshalInfoProvider { internal IMethodSignature method; internal ParameterDefinition parameter; TypeReference return_type; public IMethodSignature Method { get { return method; } } public TypeReference ReturnType { get { return return_type; } set { return_type = value; } } internal ParameterDefinition Parameter { get { if (parameter == null) parameter=new ParameterDefinition (return_type, method); return parameter; } } public MetadataToken MetadataToken { get { return Parameter.MetadataToken; } set { Parameter.MetadataToken = value; } } public ParameterAttributes Attributes { get { return Parameter.Attributes; } set { Parameter.Attributes = value; } } public bool HasCustomAttributes { get { return parameter != null && parameter.HasCustomAttributes; } } public Collection CustomAttributes { get { return Parameter.CustomAttributes; } } public bool HasDefault { get { return parameter != null && parameter.HasDefault; } set { Parameter.HasDefault = value; } } public bool HasConstant { get { return parameter != null && parameter.HasConstant; } set { Parameter.HasConstant = value; } } public object Constant { get { return Parameter.Constant; } set { Parameter.Constant = value; } } public bool HasFieldMarshal { get { return parameter != null && parameter.HasFieldMarshal; } set { Parameter.HasFieldMarshal = value; } } public bool HasMarshalInfo { get { return parameter != null && parameter.HasMarshalInfo; } } public MarshalInfo MarshalInfo { get { return Parameter.MarshalInfo; } set { Parameter.MarshalInfo = value; } } public MethodReturnType (IMethodSignature method) { this.method = method; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/MethodSemanticsAttributes.cs ================================================ // // MethodSemanticsattributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum MethodSemanticsAttributes : ushort { None = 0x0000, Setter = 0x0001, // Setter for property Getter = 0x0002, // Getter for property Other = 0x0004, // Other method for property or event AddOn = 0x0008, // AddOn method for event RemoveOn = 0x0010, // RemoveOn method for event Fire = 0x0020 // Fire method for event } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/MethodSpecification.cs ================================================ // // MethodSpecification.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Collections.Generic; namespace Mono.Cecil { public abstract class MethodSpecification : MethodReference { readonly MethodReference method; public MethodReference ElementMethod { get { return method; } } public override string Name { get { return method.Name; } set { throw new InvalidOperationException (); } } public override MethodCallingConvention CallingConvention { get { return method.CallingConvention; } set { throw new InvalidOperationException (); } } public override bool HasThis { get { return method.HasThis; } set { throw new InvalidOperationException (); } } public override bool ExplicitThis { get { return method.ExplicitThis; } set { throw new InvalidOperationException (); } } public override MethodReturnType MethodReturnType { get { return method.MethodReturnType; } set { throw new InvalidOperationException (); } } public override TypeReference DeclaringType { get { return method.DeclaringType; } set { throw new InvalidOperationException (); } } public override ModuleDefinition Module { get { return method.Module; } } public override bool HasParameters { get { return method.HasParameters; } } public override Collection Parameters { get { return method.Parameters; } } internal override bool ContainsGenericParameter { get { return method.ContainsGenericParameter; } } internal MethodSpecification (MethodReference method) { if (method == null) throw new ArgumentNullException ("method"); this.method = method; this.token = new MetadataToken (TokenType.MethodSpec); } public sealed override MethodReference GetElementMethod () { return method.GetElementMethod (); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/Modifiers.cs ================================================ // // Modifiers.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using MD = Mono.Cecil.Metadata; namespace Mono.Cecil { public interface IModifierType { TypeReference ModifierType { get; } TypeReference ElementType { get; } } public sealed class OptionalModifierType : TypeSpecification, IModifierType { TypeReference modifier_type; public TypeReference ModifierType { get { return modifier_type; } set { modifier_type = value; } } public override string Name { get { return base.Name + Suffix; } } public override string FullName { get { return base.FullName + Suffix; } } string Suffix { get { return " modopt(" + modifier_type + ")"; } } public override bool IsValueType { get { return false; } set { throw new InvalidOperationException (); } } public override bool IsOptionalModifier { get { return true; } } internal override bool ContainsGenericParameter { get { return modifier_type.ContainsGenericParameter || base.ContainsGenericParameter; } } public OptionalModifierType (TypeReference modifierType, TypeReference type) : base (type) { Mixin.CheckModifier (modifierType, type); this.modifier_type = modifierType; this.etype = MD.ElementType.CModOpt; } } public sealed class RequiredModifierType : TypeSpecification, IModifierType { TypeReference modifier_type; public TypeReference ModifierType { get { return modifier_type; } set { modifier_type = value; } } public override string Name { get { return base.Name + Suffix; } } public override string FullName { get { return base.FullName + Suffix; } } string Suffix { get { return " modreq(" + modifier_type + ")"; } } public override bool IsValueType { get { return false; } set { throw new InvalidOperationException (); } } public override bool IsRequiredModifier { get { return true; } } internal override bool ContainsGenericParameter { get { return modifier_type.ContainsGenericParameter || base.ContainsGenericParameter; } } public RequiredModifierType (TypeReference modifierType, TypeReference type) : base (type) { Mixin.CheckModifier (modifierType, type); this.modifier_type = modifierType; this.etype = MD.ElementType.CModReqD; } } static partial class Mixin { public static void CheckModifier (TypeReference modifierType, TypeReference type) { if (modifierType == null) throw new ArgumentNullException ("modifierType"); if (type == null) throw new ArgumentNullException ("type"); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/ModuleDefinition.cs ================================================ // // ModuleDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using System.IO; using System.Threading; using SR = System.Reflection; using Mono.Cecil.Cil; using Mono.Cecil.Metadata; using Mono.Cecil.PE; using Mono.Collections.Generic; namespace Mono.Cecil { public enum ReadingMode { Immediate = 1, Deferred = 2, } public sealed class ReaderParameters { ReadingMode reading_mode; IAssemblyResolver assembly_resolver; IMetadataResolver metadata_resolver; Stream symbol_stream; ISymbolReaderProvider symbol_reader_provider; bool read_symbols; public ReadingMode ReadingMode { get { return reading_mode; } set { reading_mode = value; } } public IAssemblyResolver AssemblyResolver { get { return assembly_resolver; } set { assembly_resolver = value; } } public IMetadataResolver MetadataResolver { get { return metadata_resolver; } set { metadata_resolver = value; } } public Stream SymbolStream { get { return symbol_stream; } set { symbol_stream = value; } } public ISymbolReaderProvider SymbolReaderProvider { get { return symbol_reader_provider; } set { symbol_reader_provider = value; } } public bool ReadSymbols { get { return read_symbols; } set { read_symbols = value; } } public ReaderParameters() : this(ReadingMode.Deferred) { } public ReaderParameters(ReadingMode readingMode) { this.reading_mode = readingMode; } } public sealed class ModuleDefinition : ModuleReference, ICustomAttributeProvider { internal Image Image; internal MetadataSystem MetadataSystem; internal ReadingMode ReadingMode; internal ISymbolReaderProvider SymbolReaderProvider; internal ISymbolReader symbol_reader; internal IAssemblyResolver assembly_resolver; internal IMetadataResolver metadata_resolver; internal TypeSystem type_system; readonly MetadataReader reader; readonly string fq_name; internal ModuleKind kind; TargetRuntime runtime; TargetArchitecture architecture; ModuleAttributes attributes; ModuleCharacteristics characteristics; Guid mvid; internal AssemblyDefinition assembly; MethodDefinition entry_point; Collection custom_attributes; Collection references; Collection modules; Collection resources; Collection exported_types; TypeDefinitionCollection types; public bool IsMain { get { return kind != ModuleKind.NetModule; } } public ModuleKind Kind { get { return kind; } set { kind = value; } } public TargetRuntime Runtime { get { return runtime; } set { runtime = value; } } public TargetArchitecture Architecture { get { return architecture; } set { architecture = value; } } public ModuleAttributes Attributes { get { return attributes; } set { attributes = value; } } public ModuleCharacteristics Characteristics { get { return characteristics; } set { characteristics = value; } } public string FullyQualifiedName { get { return fq_name; } } public Guid Mvid { get { return mvid; } set { mvid = value; } } internal bool HasImage { get { return Image != null; } } public bool HasSymbols { get { return symbol_reader != null; } } public ISymbolReader SymbolReader { get { return symbol_reader; } } public override MetadataScopeType MetadataScopeType { get { return MetadataScopeType.ModuleDefinition; } } public AssemblyDefinition Assembly { get { return assembly; } } public IAssemblyResolver AssemblyResolver { get { return assembly_resolver ?? (assembly_resolver = new DefaultAssemblyResolver()); } } public IMetadataResolver MetadataResolver { get { if (metadata_resolver == null) metadata_resolver=new MetadataResolver(this.AssemblyResolver); return metadata_resolver; } } public TypeSystem TypeSystem { get { if (type_system == null) type_system = TypeSystem.CreateTypeSystem(this); return type_system; } } public bool HasAssemblyReferences { get { if (references != null) return references.Count > 0; return HasImage && Image.HasTable(Table.AssemblyRef); } } public Collection AssemblyReferences { get { if (references != null) return references; if (HasImage) return Read(ref references, this, (_, reader) => reader.ReadAssemblyReferences()); return references = new Collection(); } } public bool HasModuleReferences { get { if (modules != null) return modules.Count > 0; return HasImage && Image.HasTable(Table.ModuleRef); } } public Collection ModuleReferences { get { if (modules != null) return modules; if (HasImage) return Read(ref modules, this, (_, reader) => reader.ReadModuleReferences()); return modules = new Collection(); } } public bool HasResources { get { if (resources != null) return resources.Count > 0; if (HasImage) return Image.HasTable(Table.ManifestResource) || Read(this, (_, reader) => reader.HasFileResource()); return false; } } public Collection Resources { get { if (resources != null) return resources; if (HasImage) return Read(ref resources, this, (_, reader) => reader.ReadResources()); return resources = new Collection(); } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return Mixin.GetHasCustomAttributes(this, this); } } public Collection CustomAttributes { get { return custom_attributes ?? (Mixin.GetCustomAttributes(this, ref custom_attributes, this)); } } public bool HasTypes { get { if (types != null) return types.Count > 0; return HasImage && Image.HasTable(Table.TypeDef); } } public Collection Types { get { if (types != null) return types; if (HasImage) return Read(ref types, this, (_, reader) => reader.ReadTypes()); return types = new TypeDefinitionCollection(this); } } public bool HasExportedTypes { get { if (exported_types != null) return exported_types.Count > 0; return HasImage && Image.HasTable(Table.ExportedType); } } public Collection ExportedTypes { get { if (exported_types != null) return exported_types; if (HasImage) return Read(ref exported_types, this, (_, reader) => reader.ReadExportedTypes()); return exported_types = new Collection(); } } public MethodDefinition EntryPoint { get { if (entry_point != null) return entry_point; if (HasImage) return Read(ref entry_point, this, (_, reader) => reader.ReadEntryPoint()); return entry_point = null; } set { entry_point = value; } } internal ModuleDefinition() { this.MetadataSystem = new MetadataSystem(); this.token = new MetadataToken(TokenType.Module, 1); } internal ModuleDefinition(Image image) : this() { this.Image = image; this.kind = image.Kind; this.runtime = image.Runtime; this.architecture = image.Architecture; this.attributes = image.Attributes; this.characteristics = image.Characteristics; this.fq_name = image.FileName; this.reader = new MetadataReader(this); } public bool HasTypeReference(string fullName) { return HasTypeReference(string.Empty, fullName); } public bool HasTypeReference(string scope, string fullName) { CheckFullName(fullName); if (!HasImage) return false; return GetTypeReference(scope, fullName) != null; } public bool TryGetTypeReference(string fullName, out TypeReference type) { return TryGetTypeReference(string.Empty, fullName, out type); } public bool TryGetTypeReference(string scope, string fullName, out TypeReference type) { CheckFullName(fullName); if (!HasImage) { type = null; return false; } return (type = GetTypeReference(scope, fullName)) != null; } TypeReference GetTypeReference(string scope, string fullname) { return Read(new Row(scope, fullname), (row, reader) => reader.GetTypeReference(row.Col1, row.Col2)); } public IEnumerable GetTypeReferences() { if (!HasImage) return Empty.Array; return Read(this, (_, reader) => reader.GetTypeReferences()); } public IEnumerable GetMemberReferences() { if (!HasImage) return Empty.Array; return Read(this, (_, reader) => reader.GetMemberReferences()); } public TypeReference GetType(string fullName, bool runtimeName) { return runtimeName ? TypeParser.ParseType(this, fullName) : GetType(fullName); } public TypeDefinition GetType(string fullName) { CheckFullName(fullName); var position = fullName.IndexOf('/'); if (position > 0) return GetNestedType(fullName); return ((TypeDefinitionCollection)this.Types).GetType(fullName); } public TypeDefinition GetType(string @namespace, string name) { Mixin.CheckName(name); return ((TypeDefinitionCollection)this.Types).GetType(@namespace ?? string.Empty, name); } public IEnumerable GetTypes() { return GetTypes(Types); } static IEnumerable GetTypes(Collection types) { for (int i = 0; i < types.Count; i++) { var type = types[i]; yield return type; if (!type.HasNestedTypes) continue; foreach (var nested in GetTypes(type.NestedTypes)) yield return nested; } } static void CheckFullName(string fullName) { if (fullName == null) throw new ArgumentNullException("fullName"); if (fullName.Length == 0) throw new ArgumentException(); } TypeDefinition GetNestedType(string fullname) { var names = fullname.Split('/'); var type = GetType(names[0]); if (type == null) return null; for (int i = 1; i < names.Length; i++) { var nested_type = Mixin.GetNestedType(type, names[i]); if (nested_type == null) return null; type = nested_type; } return type; } internal FieldDefinition Resolve(FieldReference field) { return MetadataResolver.Resolve(field); } internal MethodDefinition Resolve(MethodReference method) { return MetadataResolver.Resolve(method); } internal TypeDefinition Resolve(TypeReference type) { return MetadataResolver.Resolve(type); } public IMetadataTokenProvider LookupToken(int token) { return LookupToken(new MetadataToken((uint)token)); } public IMetadataTokenProvider LookupToken(MetadataToken token) { return Read(token, (t, reader) => reader.LookupToken(t)); } readonly object module_lock = new object(); internal object SyncRoot { get { return module_lock; } } internal TRet Read(TItem item, Func read) { lock (module_lock) { var position = reader.position; var context = reader.context; var ret = read(item, reader); reader.position = position; reader.context = context; return ret; } } internal TRet Read(ref TRet variable, TItem item, Func read) where TRet : class { lock (module_lock) { if (variable != null) return variable; var position = reader.position; var context = reader.context; var ret = read(item, reader); reader.position = position; reader.context = context; return variable = ret; } } public bool HasDebugHeader { get { return Image != null && !Image.Debug.IsZero; } } public ImageDebugDirectory GetDebugHeader(out byte[] header) { if (!HasDebugHeader) throw new InvalidOperationException(); return Image.GetDebugHeader(out header); } void ProcessDebugHeader() { if (!HasDebugHeader) return; byte[] header; var directory = GetDebugHeader(out header); if (!symbol_reader.ProcessDebugHeader(directory, header)) throw new InvalidOperationException(); } public void ReadSymbols() { if (string.IsNullOrEmpty(fq_name)) throw new InvalidOperationException(); var provider = SymbolProvider.GetPlatformReaderProvider(); if (provider == null) throw new InvalidOperationException(); ReadSymbols(provider.GetSymbolReader(this, fq_name)); } public void ReadSymbols(ISymbolReader reader) { if (reader == null) throw new ArgumentNullException("reader"); symbol_reader = reader; ProcessDebugHeader(); } public static ModuleDefinition ReadModule(string fileName) { return ReadModule(fileName, new ReaderParameters(ReadingMode.Deferred)); } public static ModuleDefinition ReadModule(Stream stream) { return ReadModule(stream, new ReaderParameters(ReadingMode.Deferred)); } public static ModuleDefinition ReadModule(string fileName, ReaderParameters parameters) { using (var stream = GetFileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { return ReadModule(stream, parameters); } } static void CheckStream(object stream) { if (stream == null) throw new ArgumentNullException("stream"); } public static ModuleDefinition ReadModule(Stream stream, ReaderParameters parameters) { CheckStream(stream); if (!stream.CanRead || !stream.CanSeek) throw new ArgumentException(); Mixin.CheckParameters(parameters); return ModuleReader.CreateModuleFrom( ImageReader.ReadImageFrom(stream), parameters); } static Stream GetFileStream(string fileName, FileMode mode, FileAccess access, FileShare share) { if (fileName == null) throw new ArgumentNullException("fileName"); if (fileName.Length == 0) throw new ArgumentException(); return new FileStream(fileName, mode, access, share); } } static partial class Mixin { public static void CheckParameters(object parameters) { if (parameters == null) throw new ArgumentNullException("parameters"); } public static bool HasImage(ModuleDefinition self) { return self != null && self.HasImage; } public static bool IsCorlib(ModuleDefinition module) { if (module.Assembly == null) return false; return module.Assembly.Name.Name == "mscorlib"; } public static string GetFullyQualifiedName(Stream self) { return string.Empty; } public static TargetRuntime ParseRuntime(string self) { switch (self[1]) { case '1': return self[3] == '0' ? TargetRuntime.Net_1_0 : TargetRuntime.Net_1_1; case '2': return TargetRuntime.Net_2_0; case '4': default: return TargetRuntime.Net_4_0; } } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/ModuleKind.cs ================================================ // // ModuleKind.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { public enum ModuleKind { Dll, Console, Windows, NetModule, } public enum TargetArchitecture { I386, AMD64, IA64, ARMv7, } [Flags] public enum ModuleAttributes { ILOnly = 1, Required32Bit = 2, StrongNameSigned = 8, Preferred32Bit = 0x00020000, } [Flags] public enum ModuleCharacteristics { HighEntropyVA = 0x0020, DynamicBase = 0x0040, NoSEH = 0x0400, NXCompat = 0x0100, AppContainer = 0x1000, TerminalServerAware = 0x8000, } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/ModuleReference.cs ================================================ // // ModuleReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public class ModuleReference : IMetadataScope { string name; internal MetadataToken token; public string Name { get { return name; } set { name = value; } } public virtual MetadataScopeType MetadataScopeType { get { return MetadataScopeType.ModuleReference; } } public MetadataToken MetadataToken { get { return token; } set { token = value; } } internal ModuleReference () { this.token = new MetadataToken (TokenType.ModuleRef); } public ModuleReference (string name) : this () { this.name = name; } public override string ToString () { return name; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/NativeType.cs ================================================ // // NativeType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public enum NativeType { None = 0x66, Boolean = 0x02, I1 = 0x03, U1 = 0x04, I2 = 0x05, U2 = 0x06, I4 = 0x07, U4 = 0x08, I8 = 0x09, U8 = 0x0a, R4 = 0x0b, R8 = 0x0c, LPStr = 0x14, Int = 0x1f, UInt = 0x20, Func = 0x26, Array = 0x2a, // Msft specific Currency = 0x0f, BStr = 0x13, LPWStr = 0x15, LPTStr = 0x16, FixedSysString = 0x17, IUnknown = 0x19, IDispatch = 0x1a, Struct = 0x1b, IntF = 0x1c, SafeArray = 0x1d, FixedArray = 0x1e, ByValStr = 0x22, ANSIBStr = 0x23, TBStr = 0x24, VariantBool = 0x25, ASAny = 0x28, LPStruct = 0x2b, CustomMarshaler = 0x2c, Error = 0x2d, Max = 0x50 } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/PInvokeAttributes.cs ================================================ // // PInvokeAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum PInvokeAttributes : ushort { NoMangle = 0x0001, // PInvoke is to use the member name as specified // Character set CharSetMask = 0x0006, CharSetNotSpec = 0x0000, CharSetAnsi = 0x0002, CharSetUnicode = 0x0004, CharSetAuto = 0x0006, SupportsLastError = 0x0040, // Information about target function. Not relevant for fields // Calling convetion CallConvMask = 0x0700, CallConvWinapi = 0x0100, CallConvCdecl = 0x0200, CallConvStdCall = 0x0300, CallConvThiscall = 0x0400, CallConvFastcall = 0x0500, BestFitMask = 0x0030, BestFitEnabled = 0x0010, BestFitDisabled = 0x0020, ThrowOnUnmappableCharMask = 0x3000, ThrowOnUnmappableCharEnabled = 0x1000, ThrowOnUnmappableCharDisabled = 0x2000, } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/PInvokeInfo.cs ================================================ // // PInvokeInfo.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public sealed class PInvokeInfo { ushort attributes; string entry_point; ModuleReference module; public PInvokeAttributes Attributes { get { return (PInvokeAttributes) attributes; } set { attributes = (ushort) value; } } public string EntryPoint { get { return entry_point; } set { entry_point = value; } } public ModuleReference Module { get { return module; } set { module = value; } } #region PInvokeAttributes public bool IsNoMangle { get { return Mixin.GetAttributes(attributes,(ushort) PInvokeAttributes.NoMangle); } set { attributes =Mixin.SetAttributes(attributes,(ushort) PInvokeAttributes.NoMangle, value); } } public bool IsCharSetNotSpec { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetNotSpec); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetNotSpec, value); } } public bool IsCharSetAnsi { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetAnsi); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetAnsi, value); } } public bool IsCharSetUnicode { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetUnicode); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetUnicode, value); } } public bool IsCharSetAuto { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetAuto); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetAuto, value); } } public bool SupportsLastError { get { return Mixin.GetAttributes(attributes,(ushort) PInvokeAttributes.SupportsLastError); } set { attributes =Mixin.SetAttributes(attributes,(ushort) PInvokeAttributes.SupportsLastError, value); } } public bool IsCallConvWinapi { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvWinapi); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvWinapi, value); } } public bool IsCallConvCdecl { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvCdecl); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvCdecl, value); } } public bool IsCallConvStdCall { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvStdCall); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvStdCall, value); } } public bool IsCallConvThiscall { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvThiscall); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvThiscall, value); } } public bool IsCallConvFastcall { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvFastcall); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvFastcall, value); } } public bool IsBestFitEnabled { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.BestFitMask, (ushort) PInvokeAttributes.BestFitEnabled); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.BestFitMask, (ushort) PInvokeAttributes.BestFitEnabled, value); } } public bool IsBestFitDisabled { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.BestFitMask, (ushort) PInvokeAttributes.BestFitDisabled); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.BestFitMask, (ushort) PInvokeAttributes.BestFitDisabled, value); } } public bool IsThrowOnUnmappableCharEnabled { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.ThrowOnUnmappableCharMask, (ushort) PInvokeAttributes.ThrowOnUnmappableCharEnabled); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.ThrowOnUnmappableCharMask, (ushort) PInvokeAttributes.ThrowOnUnmappableCharEnabled, value); } } public bool IsThrowOnUnmappableCharDisabled { get { return Mixin.GetMaskedAttributes(attributes,(ushort) PInvokeAttributes.ThrowOnUnmappableCharMask, (ushort) PInvokeAttributes.ThrowOnUnmappableCharDisabled); } set { attributes = Mixin.SetMaskedAttributes(attributes,(ushort) PInvokeAttributes.ThrowOnUnmappableCharMask, (ushort) PInvokeAttributes.ThrowOnUnmappableCharDisabled, value); } } #endregion public PInvokeInfo (PInvokeAttributes attributes, string entryPoint, ModuleReference module) { this.attributes = (ushort) attributes; this.entry_point = entryPoint; this.module = module; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/ParameterAttributes.cs ================================================ // // ParameterAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum ParameterAttributes : ushort { None = 0x0000, In = 0x0001, // Param is [In] Out = 0x0002, // Param is [Out] Lcid = 0x0004, Retval = 0x0008, Optional = 0x0010, // Param is optional HasDefault = 0x1000, // Param has default value HasFieldMarshal = 0x2000, // Param has field marshal Unused = 0xcfe0 // Reserved: shall be zero in a conforming implementation } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/ParameterDefinition.cs ================================================ // // ParameterDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using Mono.Collections.Generic; namespace Mono.Cecil { public sealed class ParameterDefinition : ParameterReference, ICustomAttributeProvider, IConstantProvider, IMarshalInfoProvider { ushort attributes; internal IMethodSignature method; object constant = Mixin.NotResolved; Collection custom_attributes; MarshalInfo marshal_info; public ParameterAttributes Attributes { get { return (ParameterAttributes)attributes; } set { attributes = (ushort)value; } } public IMethodSignature Method { get { return method; } } public int Sequence { get { if (method == null) return -1; return Mixin.HasImplicitThis(method) ? index + 1 : index; } } public bool HasConstant { get { Mixin.ResolveConstant(this, ref constant, parameter_type.Module); return constant != Mixin.NoValue; } set { if (!value) constant = Mixin.NoValue; } } public object Constant { get { return HasConstant ? constant : null; } set { constant = value; } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return Mixin.GetHasCustomAttributes(this, parameter_type.Module); } } public Collection CustomAttributes { get { return custom_attributes ?? (Mixin.GetCustomAttributes(this, ref custom_attributes, parameter_type.Module)); } } public bool HasMarshalInfo { get { if (marshal_info != null) return true; return Mixin.GetHasMarshalInfo(this, parameter_type.Module); } } public MarshalInfo MarshalInfo { get { return marshal_info ?? (Mixin.GetMarshalInfo(this, ref marshal_info, parameter_type.Module)); } set { marshal_info = value; } } #region ParameterAttributes public bool IsIn { get { return Mixin.GetAttributes(attributes, (ushort)ParameterAttributes.In); } set { attributes = Mixin.SetAttributes(attributes, (ushort)ParameterAttributes.In, value); } } public bool IsOut { get { return Mixin.GetAttributes(attributes, (ushort)ParameterAttributes.Out); } set { attributes = Mixin.SetAttributes(attributes, (ushort)ParameterAttributes.Out, value); } } public bool IsLcid { get { return Mixin.GetAttributes(attributes, (ushort)ParameterAttributes.Lcid); } set { attributes = Mixin.SetAttributes(attributes, (ushort)ParameterAttributes.Lcid, value); } } public bool IsReturnValue { get { return Mixin.GetAttributes(attributes, (ushort)ParameterAttributes.Retval); } set { attributes = Mixin.SetAttributes(attributes, (ushort)ParameterAttributes.Retval, value); } } public bool IsOptional { get { return Mixin.GetAttributes(attributes, (ushort)ParameterAttributes.Optional); } set { attributes = Mixin.SetAttributes(attributes, (ushort)ParameterAttributes.Optional, value); } } public bool HasDefault { get { return Mixin.GetAttributes(attributes, (ushort)ParameterAttributes.HasDefault); } set { attributes = Mixin.SetAttributes(attributes, (ushort)ParameterAttributes.HasDefault, value); } } public bool HasFieldMarshal { get { return Mixin.GetAttributes(attributes, (ushort)ParameterAttributes.HasFieldMarshal); } set { attributes = Mixin.SetAttributes(attributes, (ushort)ParameterAttributes.HasFieldMarshal, value); } } #endregion internal ParameterDefinition(TypeReference parameterType, IMethodSignature method) : this(string.Empty, ParameterAttributes.None, parameterType) { this.method = method; } public ParameterDefinition(TypeReference parameterType) : this(string.Empty, ParameterAttributes.None, parameterType) { } public ParameterDefinition(string name, ParameterAttributes attributes, TypeReference parameterType) : base(name, parameterType) { this.attributes = (ushort)attributes; this.token = new MetadataToken(TokenType.Param); } public override ParameterDefinition Resolve() { return this; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/ParameterDefinitionCollection.cs ================================================ // // ParameterDefinitionCollection.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Collections.Generic; namespace Mono.Cecil { sealed class ParameterDefinitionCollection : Collection { readonly IMethodSignature method; internal ParameterDefinitionCollection (IMethodSignature method) { this.method = method; } internal ParameterDefinitionCollection (IMethodSignature method, int capacity) : base (capacity) { this.method = method; } protected override void OnAdd (ParameterDefinition item, int index) { item.method = method; item.index = index; } protected override void OnInsert (ParameterDefinition item, int index) { item.method = method; item.index = index; for (int i = index; i < size; i++) items [i].index = i + 1; } protected override void OnSet (ParameterDefinition item, int index) { item.method = method; item.index = index; } protected override void OnRemove (ParameterDefinition item, int index) { item.method = null; item.index = -1; for (int i = index + 1; i < size; i++) items [i].index = i - 1; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/ParameterReference.cs ================================================ // // ParameterReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { public abstract class ParameterReference : IMetadataTokenProvider { string name; internal int index = -1; protected TypeReference parameter_type; internal MetadataToken token; public string Name { get { return name; } set { name = value; } } public int Index { get { return index; } } public TypeReference ParameterType { get { return parameter_type; } set { parameter_type = value; } } public MetadataToken MetadataToken { get { return token; } set { token = value; } } internal ParameterReference (string name, TypeReference parameterType) { if (parameterType == null) throw new ArgumentNullException ("parameterType"); this.name = name ?? string.Empty; this.parameter_type = parameterType; } public override string ToString () { return name; } public abstract ParameterDefinition Resolve (); } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/PinnedType.cs ================================================ // // PinnedType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using MD = Mono.Cecil.Metadata; namespace Mono.Cecil { public sealed class PinnedType : TypeSpecification { public override bool IsValueType { get { return false; } set { throw new InvalidOperationException (); } } public override bool IsPinned { get { return true; } } public PinnedType (TypeReference type) : base (type) { Mixin.CheckType (type); this.etype = MD.ElementType.Pinned; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/PointerType.cs ================================================ // // PointerType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using MD = Mono.Cecil.Metadata; namespace Mono.Cecil { public sealed class PointerType : TypeSpecification { public override string Name { get { return base.Name + "*"; } } public override string FullName { get { return base.FullName + "*"; } } public override bool IsValueType { get { return false; } set { throw new InvalidOperationException (); } } public override bool IsPointer { get { return true; } } public PointerType (TypeReference type) : base (type) { Mixin.CheckType (type); this.etype = MD.ElementType.Ptr; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/PropertyAttributes.cs ================================================ // // PropertyAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum PropertyAttributes : ushort { None = 0x0000, SpecialName = 0x0200, // Property is special RTSpecialName = 0x0400, // Runtime(metadata internal APIs) should check name encoding HasDefault = 0x1000, // Property has default Unused = 0xe9ff // Reserved: shall be zero in a conforming implementation } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/PropertyDefinition.cs ================================================ // // PropertyDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System.Text; using Mono.Collections.Generic; namespace Mono.Cecil { public sealed class PropertyDefinition : PropertyReference, IMemberDefinition, IConstantProvider { bool? has_this; ushort attributes; Collection custom_attributes; internal MethodDefinition get_method; internal MethodDefinition set_method; internal Collection other_methods; object constant = Mixin.NotResolved; public PropertyAttributes Attributes { get { return (PropertyAttributes) attributes; } set { attributes = (ushort) value; } } public bool HasThis { get { if (has_this.HasValue) return has_this.Value; if (GetMethod != null) return get_method.HasThis; if (SetMethod != null) return set_method.HasThis; return false; } set { has_this = value; } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return Mixin.GetHasCustomAttributes(this, Module); } } public Collection CustomAttributes { get { return custom_attributes ?? (Mixin.GetCustomAttributes(this, ref custom_attributes, Module)); } } public MethodDefinition GetMethod { get { if (get_method != null) return get_method; InitializeMethods (); return get_method; } set { get_method = value; } } public MethodDefinition SetMethod { get { if (set_method != null) return set_method; InitializeMethods (); return set_method; } set { set_method = value; } } public bool HasOtherMethods { get { if (other_methods != null) return other_methods.Count > 0; InitializeMethods (); return !Mixin.IsNullOrEmpty (other_methods); } } public Collection OtherMethods { get { if (other_methods != null) return other_methods; InitializeMethods (); if (other_methods != null) return other_methods; return other_methods = new Collection (); } } public bool HasParameters { get { InitializeMethods (); if (get_method != null) return get_method.HasParameters; if (set_method != null) return set_method.HasParameters && set_method.Parameters.Count > 1; return false; } } public override Collection Parameters { get { InitializeMethods (); if (get_method != null) return MirrorParameters (get_method, 0); if (set_method != null) return MirrorParameters (set_method, 1); return new Collection (); } } static Collection MirrorParameters (MethodDefinition method, int bound) { var parameters = new Collection (); if (!method.HasParameters) return parameters; var original_parameters = method.Parameters; var end = original_parameters.Count - bound; for (int i = 0; i < end; i++) parameters.Add (original_parameters [i]); return parameters; } public bool HasConstant { get { Mixin.ResolveConstant(this, ref constant, Module); return constant != Mixin.NoValue; } set { if (!value) constant = Mixin.NoValue; } } public object Constant { get { return HasConstant ? constant : null; } set { constant = value; } } #region PropertyAttributes public bool IsSpecialName { get { return Mixin.GetAttributes(attributes,(ushort) PropertyAttributes.SpecialName); } set { attributes =Mixin.SetAttributes(attributes,(ushort) PropertyAttributes.SpecialName, value); } } public bool IsRuntimeSpecialName { get { return Mixin.GetAttributes(attributes,(ushort) PropertyAttributes.RTSpecialName); } set { attributes =Mixin.SetAttributes(attributes,(ushort) PropertyAttributes.RTSpecialName, value); } } public bool HasDefault { get { return Mixin.GetAttributes(attributes,(ushort) PropertyAttributes.HasDefault); } set { attributes =Mixin.SetAttributes(attributes,(ushort) PropertyAttributes.HasDefault, value); } } #endregion public new TypeDefinition DeclaringType { get { return (TypeDefinition) base.DeclaringType; } set { base.DeclaringType = value; } } public override bool IsDefinition { get { return true; } } public override string FullName { get { var builder = new StringBuilder (); builder.Append (PropertyType.ToString ()); builder.Append (' '); builder.Append (MemberFullName ()); builder.Append ('('); if (HasParameters) { var parameters = Parameters; for (int i = 0; i < parameters.Count; i++) { if (i > 0) builder.Append (','); builder.Append (parameters [i].ParameterType.FullName); } } builder.Append (')'); return builder.ToString (); } } public PropertyDefinition (string name, PropertyAttributes attributes, TypeReference propertyType) : base (name, propertyType) { this.attributes = (ushort) attributes; this.token = new MetadataToken (TokenType.Property); } void InitializeMethods () { var module = this.Module; lock (module.SyncRoot) { if (get_method != null || set_method != null) return; if (!Mixin.HasImage(module)) return; module.Read (this, (property, reader) => reader.ReadMethods (property)); } } public override PropertyDefinition Resolve () { return this; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/PropertyReference.cs ================================================ // // PropertyReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Collections.Generic; namespace Mono.Cecil { public abstract class PropertyReference : MemberReference { TypeReference property_type; public TypeReference PropertyType { get { return property_type; } set { property_type = value; } } public abstract Collection Parameters { get; } internal PropertyReference (string name, TypeReference propertyType) : base (name) { if (propertyType == null) throw new ArgumentNullException ("propertyType"); property_type = propertyType; } public abstract PropertyDefinition Resolve (); } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/ReferenceType.cs ================================================ // // ByReferenceType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using MD = Mono.Cecil.Metadata; namespace Mono.Cecil { public sealed class ByReferenceType : TypeSpecification { public override string Name { get { return base.Name + "&"; } } public override string FullName { get { return base.FullName + "&"; } } public override bool IsValueType { get { return false; } set { throw new InvalidOperationException (); } } public override bool IsByReference { get { return true; } } public ByReferenceType (TypeReference type) : base (type) { Mixin.CheckType (type); this.etype = MD.ElementType.ByRef; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/Resource.cs ================================================ // // ResourceType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public enum ResourceType { Linked, Embedded, AssemblyLinked, } public abstract class Resource { string name; uint attributes; public string Name { get { return name; } set { name = value; } } public ManifestResourceAttributes Attributes { get { return (ManifestResourceAttributes) attributes; } set { attributes = (uint) value; } } public abstract ResourceType ResourceType { get; } #region ManifestResourceAttributes public bool IsPublic { get { return Mixin.GetMaskedAttributes(attributes,(uint) ManifestResourceAttributes.VisibilityMask, (uint) ManifestResourceAttributes.Public); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) ManifestResourceAttributes.VisibilityMask, (uint) ManifestResourceAttributes.Public, value); } } public bool IsPrivate { get { return Mixin.GetMaskedAttributes(attributes,(uint) ManifestResourceAttributes.VisibilityMask, (uint) ManifestResourceAttributes.Private); } set { attributes = Mixin.SetMaskedAttributes(attributes,(uint) ManifestResourceAttributes.VisibilityMask, (uint) ManifestResourceAttributes.Private, value); } } #endregion internal Resource (string name, ManifestResourceAttributes attributes) { this.name = name; this.attributes = (uint) attributes; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/SecurityDeclaration.cs ================================================ // // SecurityDeclaration.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Threading; using Mono.Collections.Generic; namespace Mono.Cecil { public enum SecurityAction : ushort { Request = 1, Demand = 2, Assert = 3, Deny = 4, PermitOnly = 5, LinkDemand = 6, InheritDemand = 7, RequestMinimum = 8, RequestOptional = 9, RequestRefuse = 10, PreJitGrant = 11, PreJitDeny = 12, NonCasDemand = 13, NonCasLinkDemand = 14, NonCasInheritance = 15 } public interface ISecurityDeclarationProvider : IMetadataTokenProvider { bool HasSecurityDeclarations { get; } Collection SecurityDeclarations { get; } } public sealed class SecurityAttribute : ICustomAttribute { TypeReference attribute_type; internal Collection fields; internal Collection properties; public TypeReference AttributeType { get { return attribute_type; } set { attribute_type = value; } } public bool HasFields { get { return !Mixin.IsNullOrEmpty(fields); } } public Collection Fields { get { return fields ?? (fields = new Collection()); } } public bool HasProperties { get { return !Mixin.IsNullOrEmpty(properties); } } public Collection Properties { get { return properties ?? (properties = new Collection()); } } public SecurityAttribute(TypeReference attributeType) { this.attribute_type = attributeType; } } public sealed class SecurityDeclaration { readonly internal uint signature; byte[] blob; readonly ModuleDefinition module; internal bool resolved; SecurityAction action; internal Collection security_attributes; public SecurityAction Action { get { return action; } set { action = value; } } public bool HasSecurityAttributes { get { Resolve(); return !Mixin.IsNullOrEmpty(security_attributes); } } public Collection SecurityAttributes { get { Resolve(); return security_attributes ?? (security_attributes = new Collection()); } } internal bool HasImage { get { return module != null && module.HasImage; } } internal SecurityDeclaration(SecurityAction action, uint signature, ModuleDefinition module) { this.action = action; this.signature = signature; this.module = module; } public SecurityDeclaration(SecurityAction action) { this.action = action; this.resolved = true; } public SecurityDeclaration(SecurityAction action, byte[] blob) { this.action = action; this.resolved = false; this.blob = blob; } public byte[] GetBlob() { if (blob != null) return blob; if (!HasImage || signature == 0) throw new NotSupportedException(); return blob = module.Read(this, (declaration, reader) => reader.ReadSecurityDeclarationBlob(declaration.signature)); } void Resolve() { if (resolved || !HasImage) return; module.Read(this, (declaration, reader) => { reader.ReadSecurityDeclarationSignature(declaration); return this; }); resolved = true; } } static partial class Mixin { public static bool GetHasSecurityDeclarations( ISecurityDeclarationProvider self, ModuleDefinition module) { return Mixin.HasImage(module) && module.Read(self, (provider, reader) => reader.HasSecurityDeclarations(provider)); } public static Collection GetSecurityDeclarations( ISecurityDeclarationProvider self, ref Collection variable, ModuleDefinition module) { return Mixin.HasImage(module) ? module.Read(ref variable, self, (provider, reader) => reader.ReadSecurityDeclarations(provider)) : variable = new Collection(); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/SentinelType.cs ================================================ // // SentinelType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using MD = Mono.Cecil.Metadata; namespace Mono.Cecil { public sealed class SentinelType : TypeSpecification { public override bool IsValueType { get { return false; } set { throw new InvalidOperationException (); } } public override bool IsSentinel { get { return true; } } public SentinelType (TypeReference type) : base (type) { Mixin.CheckType (type); this.etype = MD.ElementType.Sentinel; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/TargetRuntime.cs ================================================ // // TargetRuntime.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public enum TargetRuntime { Net_1_0, Net_1_1, Net_2_0, Net_4_0, } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/TypeAttributes.cs ================================================ // // TypeAttributes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil { [Flags] public enum TypeAttributes : uint { // Visibility attributes VisibilityMask = 0x00000007, // Use this mask to retrieve visibility information NotPublic = 0x00000000, // Class has no public scope Public = 0x00000001, // Class has public scope NestedPublic = 0x00000002, // Class is nested with public visibility NestedPrivate = 0x00000003, // Class is nested with private visibility NestedFamily = 0x00000004, // Class is nested with family visibility NestedAssembly = 0x00000005, // Class is nested with assembly visibility NestedFamANDAssem = 0x00000006, // Class is nested with family and assembly visibility NestedFamORAssem = 0x00000007, // Class is nested with family or assembly visibility // Class layout attributes LayoutMask = 0x00000018, // Use this mask to retrieve class layout information AutoLayout = 0x00000000, // Class fields are auto-laid out SequentialLayout = 0x00000008, // Class fields are laid out sequentially ExplicitLayout = 0x00000010, // Layout is supplied explicitly // Class semantics attributes ClassSemanticMask = 0x00000020, // Use this mask to retrieve class semantics information Class = 0x00000000, // Type is a class Interface = 0x00000020, // Type is an interface // Special semantics in addition to class semantics Abstract = 0x00000080, // Class is abstract Sealed = 0x00000100, // Class cannot be extended SpecialName = 0x00000400, // Class name is special // Implementation attributes Import = 0x00001000, // Class/Interface is imported Serializable = 0x00002000, // Class is serializable WindowsRuntime = 0x00004000, // Windows Runtime type // String formatting attributes StringFormatMask = 0x00030000, // Use this mask to retrieve string information for native interop AnsiClass = 0x00000000, // LPSTR is interpreted as ANSI UnicodeClass = 0x00010000, // LPSTR is interpreted as Unicode AutoClass = 0x00020000, // LPSTR is interpreted automatically // Class initialization attributes BeforeFieldInit = 0x00100000, // Initialize the class before first static field access // Additional flags RTSpecialName = 0x00000800, // CLI provides 'special' behavior, depending upon the name of the Type HasSecurity = 0x00040000, // Type has security associate with it Forwarder = 0x00200000, // Exported type is a type forwarder } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/TypeDefinition.cs ================================================ // // TypeDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.Metadata; using Mono.Collections.Generic; namespace Mono.Cecil { public sealed class TypeDefinition : TypeReference, IMemberDefinition, ISecurityDeclarationProvider { uint attributes; TypeReference base_type; internal Range fields_range; internal Range methods_range; short packing_size = Mixin.NotResolvedMarker; int class_size = Mixin.NotResolvedMarker; Collection interfaces; Collection nested_types; Collection methods; Collection fields; Collection events; Collection properties; Collection custom_attributes; Collection security_declarations; public TypeAttributes Attributes { get { return (TypeAttributes)attributes; } set { attributes = (uint)value; } } public TypeReference BaseType { get { return base_type; } set { base_type = value; } } void ResolveLayout() { if (packing_size != Mixin.NotResolvedMarker || class_size != Mixin.NotResolvedMarker) return; if (!HasImage) { packing_size = Mixin.NoDataMarker; class_size = Mixin.NoDataMarker; return; } var row = Module.Read(this, (type, reader) => reader.ReadTypeLayout(type)); packing_size = row.Col1; class_size = row.Col2; } public bool HasLayoutInfo { get { if (packing_size >= 0 || class_size >= 0) return true; ResolveLayout(); return packing_size >= 0 || class_size >= 0; } } public short PackingSize { get { if (packing_size >= 0) return packing_size; ResolveLayout(); return packing_size >= 0 ? packing_size : (short)-1; } set { packing_size = value; } } public int ClassSize { get { if (class_size >= 0) return class_size; ResolveLayout(); return class_size >= 0 ? class_size : -1; } set { class_size = value; } } public bool HasInterfaces { get { if (interfaces != null) return interfaces.Count > 0; if (HasImage) return Module.Read(this, (type, reader) => reader.HasInterfaces(type)); return false; } } public Collection Interfaces { get { if (interfaces != null) return interfaces; if (HasImage) return Module.Read(ref interfaces, this, (type, reader) => reader.ReadInterfaces(type)); return interfaces = new Collection(); } } public bool HasNestedTypes { get { if (nested_types != null) return nested_types.Count > 0; if (HasImage) return Module.Read(this, (type, reader) => reader.HasNestedTypes(type)); return false; } } public Collection NestedTypes { get { if (nested_types != null) return nested_types; if (HasImage) return Module.Read(ref nested_types, this, (type, reader) => reader.ReadNestedTypes(type)); return nested_types = new MemberDefinitionCollection(this); } } public bool HasMethods { get { if (methods != null) return methods.Count > 0; if (HasImage) return methods_range.Length > 0; return false; } } public Collection Methods { get { if (methods != null) return methods; if (HasImage) return Module.Read(ref methods, this, (type, reader) => reader.ReadMethods(type)); return methods = new MemberDefinitionCollection(this); } } public bool HasFields { get { if (fields != null) return fields.Count > 0; if (HasImage) return fields_range.Length > 0; return false; } } public Collection Fields { get { if (fields != null) return fields; if (HasImage) return Module.Read(ref fields, this, (type, reader) => reader.ReadFields(type)); return fields = new MemberDefinitionCollection(this); } } public bool HasEvents { get { if (events != null) return events.Count > 0; if (HasImage) return Module.Read(this, (type, reader) => reader.HasEvents(type)); return false; } } public Collection Events { get { if (events != null) return events; if (HasImage) return Module.Read(ref events, this, (type, reader) => reader.ReadEvents(type)); return events = new MemberDefinitionCollection(this); } } public bool HasProperties { get { if (properties != null) return properties.Count > 0; if (HasImage) return Module.Read(this, (type, reader) => reader.HasProperties(type)); return false; } } public Collection Properties { get { if (properties != null) return properties; if (HasImage) return Module.Read(ref properties, this, (type, reader) => reader.ReadProperties(type)); return properties = new MemberDefinitionCollection(this); } } public bool HasSecurityDeclarations { get { if (security_declarations != null) return security_declarations.Count > 0; return Mixin.GetHasSecurityDeclarations(this, Module); } } public Collection SecurityDeclarations { get { return security_declarations ?? (Mixin.GetSecurityDeclarations(this, ref security_declarations, Module)); } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return Mixin.GetHasCustomAttributes(this, Module); } } public Collection CustomAttributes { get { return custom_attributes ?? (Mixin.GetCustomAttributes(this, ref custom_attributes, Module)); } } public override bool HasGenericParameters { get { if (generic_parameters != null) return generic_parameters.Count > 0; return Mixin.GetHasGenericParameters(this, Module); } } public override Collection GenericParameters { get { return generic_parameters ?? (Mixin.GetGenericParameters(this,ref generic_parameters, Module)); } } #region TypeAttributes public bool IsNotPublic { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NotPublic); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NotPublic, value); } } public bool IsPublic { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.Public); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.Public, value); } } public bool IsNestedPublic { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedPublic); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedPublic, value); } } public bool IsNestedPrivate { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedPrivate); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedPrivate, value); } } public bool IsNestedFamily { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamily); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamily, value); } } public bool IsNestedAssembly { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedAssembly); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedAssembly, value); } } public bool IsNestedFamilyAndAssembly { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamANDAssem); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamANDAssem, value); } } public bool IsNestedFamilyOrAssembly { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamORAssem); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamORAssem, value); } } public bool IsAutoLayout { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.AutoLayout); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.AutoLayout, value); } } public bool IsSequentialLayout { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.SequentialLayout); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.SequentialLayout, value); } } public bool IsExplicitLayout { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.ExplicitLayout); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.ExplicitLayout, value); } } public bool IsClass { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.ClassSemanticMask, (uint)TypeAttributes.Class); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.ClassSemanticMask, (uint)TypeAttributes.Class, value); } } public bool IsInterface { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.ClassSemanticMask, (uint)TypeAttributes.Interface); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.ClassSemanticMask, (uint)TypeAttributes.Interface, value); } } public bool IsAbstract { get { return Mixin.GetAttributes(attributes, (uint)TypeAttributes.Abstract); } set { attributes = Mixin.SetAttributes(attributes, (uint)TypeAttributes.Abstract, value); } } public bool IsSealed { get { return Mixin.GetAttributes(attributes, (uint)TypeAttributes.Sealed); } set { attributes = Mixin.SetAttributes(attributes, (uint)TypeAttributes.Sealed, value); } } public bool IsSpecialName { get { return Mixin.GetAttributes(attributes, (uint)TypeAttributes.SpecialName); } set { attributes = Mixin.SetAttributes(attributes, (uint)TypeAttributes.SpecialName, value); } } public bool IsImport { get { return Mixin.GetAttributes(attributes, (uint)TypeAttributes.Import); } set { attributes = Mixin.SetAttributes(attributes, (uint)TypeAttributes.Import, value); } } public bool IsSerializable { get { return Mixin.GetAttributes(attributes, (uint)TypeAttributes.Serializable); } set { attributes = Mixin.SetAttributes(attributes, (uint)TypeAttributes.Serializable, value); } } public bool IsWindowsRuntime { get { return Mixin.GetAttributes(attributes, (uint)TypeAttributes.WindowsRuntime); } set { attributes = Mixin.SetAttributes(attributes, (uint)TypeAttributes.WindowsRuntime, value); } } public bool IsAnsiClass { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.AnsiClass); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.AnsiClass, value); } } public bool IsUnicodeClass { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.UnicodeClass); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.UnicodeClass, value); } } public bool IsAutoClass { get { return Mixin.GetMaskedAttributes(attributes, (uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.AutoClass); } set { attributes = Mixin.SetMaskedAttributes(attributes, (uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.AutoClass, value); } } public bool IsBeforeFieldInit { get { return Mixin.GetAttributes(attributes, (uint)TypeAttributes.BeforeFieldInit); } set { attributes = Mixin.SetAttributes(attributes, (uint)TypeAttributes.BeforeFieldInit, value); } } public bool IsRuntimeSpecialName { get { return Mixin.GetAttributes(attributes, (uint)TypeAttributes.RTSpecialName); } set { attributes = Mixin.SetAttributes(attributes, (uint)TypeAttributes.RTSpecialName, value); } } public bool HasSecurity { get { return Mixin.GetAttributes(attributes, (uint)TypeAttributes.HasSecurity); } set { attributes = Mixin.SetAttributes(attributes, (uint)TypeAttributes.HasSecurity, value); } } #endregion public bool IsEnum { get { return base_type != null && Mixin.IsTypeOf(base_type, "System", "Enum"); } } public override bool IsValueType { get { if (base_type == null) return false; return Mixin.IsTypeOf(base_type, "System", "Enum") || (Mixin.IsTypeOf(base_type, "System", "ValueType") && !Mixin.IsTypeOf(this, "System", "Enum")); } } public override bool IsPrimitive { get { ElementType primitive_etype; return MetadataSystem.TryGetPrimitiveElementType(this, out primitive_etype); } } public override MetadataType MetadataType { get { ElementType primitive_etype; if (MetadataSystem.TryGetPrimitiveElementType(this, out primitive_etype)) return (MetadataType)primitive_etype; return base.MetadataType; } } public override bool IsDefinition { get { return true; } } public new TypeDefinition DeclaringType { get { return (TypeDefinition)base.DeclaringType; } set { base.DeclaringType = value; } } public TypeDefinition(string @namespace, string name, TypeAttributes attributes) : base(@namespace, name) { this.attributes = (uint)attributes; this.token = new MetadataToken(TokenType.TypeDef); } public TypeDefinition(string @namespace, string name, TypeAttributes attributes, TypeReference baseType) : this(@namespace, name, attributes) { this.BaseType = baseType; } public override TypeDefinition Resolve() { return this; } } static partial class Mixin { public static TypeReference GetEnumUnderlyingType(TypeDefinition self) { var fields = self.Fields; for (int i = 0; i < fields.Count; i++) { var field = fields[i]; if (!field.IsStatic) return field.FieldType; } throw new ArgumentException(); } public static TypeDefinition GetNestedType(TypeDefinition self, string name) { if (!self.HasNestedTypes) return null; var nested_types = self.NestedTypes; for (int i = 0; i < nested_types.Count; i++) { var nested_type = nested_types[i]; if (nested_type.Name == name) return nested_type; } return null; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/TypeDefinitionCollection.cs ================================================ // // TypeDefinitionCollection.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using Mono.Cecil.Metadata; using Mono.Collections.Generic; namespace Mono.Cecil { using Slot = Row; sealed class TypeDefinitionCollection : Collection { readonly ModuleDefinition container; readonly Dictionary name_cache; internal TypeDefinitionCollection (ModuleDefinition container) { this.container = container; this.name_cache = new Dictionary (new RowEqualityComparer ()); } internal TypeDefinitionCollection (ModuleDefinition container, int capacity) : base (capacity) { this.container = container; this.name_cache = new Dictionary (capacity, new RowEqualityComparer ()); } protected override void OnAdd (TypeDefinition item, int index) { Attach (item); } protected override void OnSet (TypeDefinition item, int index) { Attach (item); } protected override void OnInsert (TypeDefinition item, int index) { Attach (item); } protected override void OnRemove (TypeDefinition item, int index) { Detach (item); } protected override void OnClear () { foreach (var type in this) Detach (type); } void Attach (TypeDefinition type) { if (type.Module != null && type.Module != container) throw new ArgumentException ("Type already attached"); type.module = container; type.scope = container; name_cache [new Slot (type.Namespace, type.Name)] = type; } void Detach (TypeDefinition type) { type.module = null; type.scope = null; name_cache.Remove (new Slot (type.Namespace, type.Name)); } public TypeDefinition GetType (string fullname) { string @namespace, name; TypeParser.SplitFullName (fullname, out @namespace, out name); return GetType (@namespace, name); } public TypeDefinition GetType (string @namespace, string name) { TypeDefinition type; if (name_cache.TryGetValue (new Slot (@namespace, name), out type)) return type; return null; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/TypeParser.cs ================================================ // // TypeParser.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Text; using Mono.Cecil.Metadata; namespace Mono.Cecil { class TypeParser { class Type { public const int Ptr = -1; public const int ByRef = -2; public const int SzArray = -3; public string type_fullname; public string[] nested_names; public int arity; public int[] specs; public Type[] generic_arguments; public string assembly; } readonly string fullname; readonly int length; int position; TypeParser(string fullname) { this.fullname = fullname; this.length = fullname.Length; } Type ParseType(bool fq_name) { var type = new Type(); type.type_fullname = ParsePart(); type.nested_names = ParseNestedNames(); if (TryGetArity(type)) type.generic_arguments = ParseGenericArguments(type.arity); type.specs = ParseSpecs(); if (fq_name) type.assembly = ParseAssemblyName(); return type; } static bool TryGetArity(Type type) { int arity = 0; TryAddArity(type.type_fullname, ref arity); var nested_names = type.nested_names; if (!Mixin.IsNullOrEmpty(nested_names)) { for (int i = 0; i < nested_names.Length; i++) TryAddArity(nested_names[i], ref arity); } type.arity = arity; return arity > 0; } static bool TryGetArity(string name, out int arity) { arity = 0; var index = name.LastIndexOf('`'); if (index == -1) return false; return ParseInt32(name.Substring(index + 1), out arity); } static bool ParseInt32(string value, out int result) { #if CF try { result = int.Parse (value); return true; } catch { result = 0; return false; } #else return int.TryParse(value, out result); #endif } static void TryAddArity(string name, ref int arity) { int type_arity; if (!TryGetArity(name, out type_arity)) return; arity += type_arity; } string ParsePart() { int start = position; while (position < length && !IsDelimiter(fullname[position])) position++; return fullname.Substring(start, position - start); } static bool IsDelimiter(char chr) { return "+,[]*&".IndexOf(chr) != -1; } void TryParseWhiteSpace() { while (position < length && Char.IsWhiteSpace(fullname[position])) position++; } string[] ParseNestedNames() { string[] nested_names = null; while (TryParse('+')) Add(ref nested_names, ParsePart()); return nested_names; } bool TryParse(char chr) { if (position < length && fullname[position] == chr) { position++; return true; } return false; } static void Add(ref T[] array, T item) { if (array == null) { array = new[] { item }; return; } #if !CF Array.Resize(ref array, array.Length + 1); #else var copy = new T [array.Length + 1]; Array.Copy (array, copy, array.Length); array = copy; #endif array[array.Length - 1] = item; } int[] ParseSpecs() { int[] specs = null; while (position < length) { switch (fullname[position]) { case '*': position++; Add(ref specs, Type.Ptr); break; case '&': position++; Add(ref specs, Type.ByRef); break; case '[': position++; switch (fullname[position]) { case ']': position++; Add(ref specs, Type.SzArray); break; case '*': position++; Add(ref specs, 1); break; default: var rank = 1; while (TryParse(',')) rank++; Add(ref specs, rank); TryParse(']'); break; } break; default: return specs; } } return specs; } Type[] ParseGenericArguments(int arity) { Type[] generic_arguments = null; if (position == length || fullname[position] != '[') return generic_arguments; TryParse('['); for (int i = 0; i < arity; i++) { var fq_argument = TryParse('['); Add(ref generic_arguments, ParseType(fq_argument)); if (fq_argument) TryParse(']'); TryParse(','); TryParseWhiteSpace(); } TryParse(']'); return generic_arguments; } string ParseAssemblyName() { if (!TryParse(',')) return string.Empty; TryParseWhiteSpace(); var start = position; while (position < length) { var chr = fullname[position]; if (chr == '[' || chr == ']') break; position++; } return fullname.Substring(start, position - start); } public static TypeReference ParseType(ModuleDefinition module, string fullname) { if (string.IsNullOrEmpty(fullname)) return null; var parser = new TypeParser(fullname); return GetTypeReference(module, parser.ParseType(true)); } static TypeReference GetTypeReference(ModuleDefinition module, Type type_info) { TypeReference type; if (!TryGetDefinition(module, type_info, out type)) type = CreateReference(type_info, module, GetMetadataScope(module, type_info)); return CreateSpecs(type, type_info); } static TypeReference CreateSpecs(TypeReference type, Type type_info) { type = TryCreateGenericInstanceType(type, type_info); var specs = type_info.specs; if (Mixin.IsNullOrEmpty(specs)) return type; for (int i = 0; i < specs.Length; i++) { switch (specs[i]) { case Type.Ptr: type = new PointerType(type); break; case Type.ByRef: type = new ByReferenceType(type); break; case Type.SzArray: type = new ArrayType(type); break; default: var array = new ArrayType(type); array.Dimensions.Clear(); for (int j = 0; j < specs[i]; j++) array.Dimensions.Add(new ArrayDimension()); type = array; break; } } return type; } static TypeReference TryCreateGenericInstanceType(TypeReference type, Type type_info) { var generic_arguments = type_info.generic_arguments; if (Mixin.IsNullOrEmpty(generic_arguments)) return type; var instance = new GenericInstanceType(type); var instance_arguments = instance.GenericArguments; for (int i = 0; i < generic_arguments.Length; i++) instance_arguments.Add(GetTypeReference(type.Module, generic_arguments[i])); return instance; } public static void SplitFullName(string fullname, out string @namespace, out string name) { var last_dot = fullname.LastIndexOf('.'); if (last_dot == -1) { @namespace = string.Empty; name = fullname; } else { @namespace = fullname.Substring(0, last_dot); name = fullname.Substring(last_dot + 1); } } static TypeReference CreateReference(Type type_info, ModuleDefinition module, IMetadataScope scope) { string @namespace, name; SplitFullName(type_info.type_fullname, out @namespace, out name); var type = new TypeReference(@namespace, name, module, scope); MetadataSystem.TryProcessPrimitiveTypeReference(type); AdjustGenericParameters(type); var nested_names = type_info.nested_names; if (Mixin.IsNullOrEmpty(nested_names)) return type; for (int i = 0; i < nested_names.Length; i++) { type = new TypeReference(string.Empty, nested_names[i], module, null) { DeclaringType = type, }; AdjustGenericParameters(type); } return type; } static void AdjustGenericParameters(TypeReference type) { int arity; if (!TryGetArity(type.Name, out arity)) return; for (int i = 0; i < arity; i++) type.GenericParameters.Add(new GenericParameter(type)); } static IMetadataScope GetMetadataScope(ModuleDefinition module, Type type_info) { if (string.IsNullOrEmpty(type_info.assembly)) return module.TypeSystem.Corlib; return MatchReference(module, AssemblyNameReference.Parse(type_info.assembly)); } static AssemblyNameReference MatchReference(ModuleDefinition module, AssemblyNameReference pattern) { var references = module.AssemblyReferences; for (int i = 0; i < references.Count; i++) { var reference = references[i]; if (reference.FullName == pattern.FullName) return reference; } return pattern; } static bool TryGetDefinition(ModuleDefinition module, Type type_info, out TypeReference type) { type = null; if (!TryCurrentModule(module, type_info)) return false; var typedef = module.GetType(type_info.type_fullname); if (typedef == null) return false; var nested_names = type_info.nested_names; if (!Mixin.IsNullOrEmpty(nested_names)) { for (int i = 0; i < nested_names.Length; i++) typedef = Mixin.GetNestedType(typedef, nested_names[i]); } type = typedef; return true; } static bool TryCurrentModule(ModuleDefinition module, Type type_info) { if (string.IsNullOrEmpty(type_info.assembly)) return true; if (module.assembly != null && module.assembly.Name.FullName == type_info.assembly) return true; return false; } public static string ToParseable(TypeReference type) { if (type == null) return null; var name = new StringBuilder(); AppendType(type, name, true, true); return name.ToString(); } static void AppendType(TypeReference type, StringBuilder name, bool fq_name, bool top_level) { var declaring_type = type.DeclaringType; if (declaring_type != null) { AppendType(declaring_type, name, false, top_level); name.Append('+'); } var @namespace = type.Namespace; if (!string.IsNullOrEmpty(@namespace)) { name.Append(@namespace); name.Append('.'); } name.Append(type.GetElementType().Name); if (!fq_name) return; if (Mixin.IsTypeSpecification(type)) AppendTypeSpecification((TypeSpecification)type, name); if (RequiresFullyQualifiedName(type, top_level)) { name.Append(", "); name.Append(GetScopeFullName(type)); } } static string GetScopeFullName(TypeReference type) { var scope = type.Scope; switch (scope.MetadataScopeType) { case MetadataScopeType.AssemblyNameReference: return ((AssemblyNameReference)scope).FullName; case MetadataScopeType.ModuleDefinition: return ((ModuleDefinition)scope).Assembly.Name.FullName; } throw new ArgumentException(); } static void AppendTypeSpecification(TypeSpecification type, StringBuilder name) { if (Mixin.IsTypeSpecification(type.ElementType)) AppendTypeSpecification((TypeSpecification)type.ElementType, name); switch (type.etype) { case ElementType.Ptr: name.Append('*'); break; case ElementType.ByRef: name.Append('&'); break; case ElementType.SzArray: case ElementType.Array: var array = (ArrayType)type; if (array.IsVector) { name.Append("[]"); } else { name.Append('['); for (int i = 1; i < array.Rank; i++) name.Append(','); name.Append(']'); } break; case ElementType.GenericInst: var instance = (GenericInstanceType)type; var arguments = instance.GenericArguments; name.Append('['); for (int i = 0; i < arguments.Count; i++) { if (i > 0) name.Append(','); var argument = arguments[i]; var requires_fqname = argument.Scope != argument.Module; if (requires_fqname) name.Append('['); AppendType(argument, name, true, false); if (requires_fqname) name.Append(']'); } name.Append(']'); break; default: return; } } static bool RequiresFullyQualifiedName(TypeReference type, bool top_level) { if (type.Scope == type.Module) return false; if (type.Scope.Name == "mscorlib" && top_level) return false; return true; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/TypeReference.cs ================================================ // // TypeReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.Metadata; using Mono.Collections.Generic; namespace Mono.Cecil { public enum MetadataType : byte { Void = ElementType.Void, Boolean = ElementType.Boolean, Char = ElementType.Char, SByte = ElementType.I1, Byte = ElementType.U1, Int16 = ElementType.I2, UInt16 = ElementType.U2, Int32 = ElementType.I4, UInt32 = ElementType.U4, Int64 = ElementType.I8, UInt64 = ElementType.U8, Single = ElementType.R4, Double = ElementType.R8, String = ElementType.String, Pointer = ElementType.Ptr, ByReference = ElementType.ByRef, ValueType = ElementType.ValueType, Class = ElementType.Class, Var = ElementType.Var, Array = ElementType.Array, GenericInstance = ElementType.GenericInst, TypedByReference = ElementType.TypedByRef, IntPtr = ElementType.I, UIntPtr = ElementType.U, FunctionPointer = ElementType.FnPtr, Object = ElementType.Object, MVar = ElementType.MVar, RequiredModifier = ElementType.CModReqD, OptionalModifier = ElementType.CModOpt, Sentinel = ElementType.Sentinel, Pinned = ElementType.Pinned, } public class TypeReference : MemberReference, IGenericParameterProvider, IGenericContext { string @namespace; bool value_type; int hashCode = -1; static int instance_id; internal IMetadataScope scope; internal ModuleDefinition module; internal ElementType etype = ElementType.None; string fullname; protected Collection generic_parameters; public override string Name { get { return base.Name; } set { base.Name = value; fullname = null; } } public virtual string Namespace { get { return @namespace; } set { @namespace = value; fullname = null; } } public virtual bool IsValueType { get { return value_type; } set { value_type = value; } } public override ModuleDefinition Module { get { if (module != null) return module; var declaring_type = this.DeclaringType; if (declaring_type != null) return declaring_type.Module; return null; } } IGenericParameterProvider IGenericContext.Type { get { return this; } } IGenericParameterProvider IGenericContext.Method { get { return null; } } GenericParameterType IGenericParameterProvider.GenericParameterType { get { return GenericParameterType.Type; } } public virtual bool HasGenericParameters { get { return !Mixin.IsNullOrEmpty(generic_parameters); } } public virtual Collection GenericParameters { get { if (generic_parameters != null) return generic_parameters; return generic_parameters = new GenericParameterCollection(this); } } public virtual IMetadataScope Scope { get { var declaring_type = this.DeclaringType; if (declaring_type != null) return declaring_type.Scope; return scope; } } public bool IsNested { get { return this.DeclaringType != null; } } public override TypeReference DeclaringType { get { return base.DeclaringType; } set { base.DeclaringType = value; fullname = null; } } public override string FullName { get { if (fullname != null) return fullname; if (IsNested) return fullname = DeclaringType.FullName + "/" + Name; if (string.IsNullOrEmpty(@namespace)) return fullname = Name; return fullname = @namespace + "." + Name; } } public virtual bool IsByReference { get { return false; } } public virtual bool IsPointer { get { return false; } } public virtual bool IsSentinel { get { return false; } } public virtual bool IsArray { get { return false; } } public virtual bool IsGenericParameter { get { return false; } } public virtual bool IsGenericInstance { get { return false; } } public virtual bool IsRequiredModifier { get { return false; } } public virtual bool IsOptionalModifier { get { return false; } } public virtual bool IsPinned { get { return false; } } public virtual bool IsFunctionPointer { get { return false; } } public override int GetHashCode() { if (hashCode == -1) hashCode = System.Threading.Interlocked.Add(ref instance_id, 1); return hashCode; } public virtual bool IsPrimitive { get { return Mixin.IsPrimitive(etype); } } public virtual MetadataType MetadataType { get { switch (etype) { case ElementType.None: return IsValueType ? MetadataType.ValueType : MetadataType.Class; default: return (MetadataType)etype; } } } protected TypeReference(string @namespace, string name) : base(name) { this.@namespace = @namespace ?? string.Empty; this.token = new MetadataToken(TokenType.TypeRef, 0); } public TypeReference(string @namespace, string name, ModuleDefinition module, IMetadataScope scope) : this(@namespace, name) { this.module = module; this.scope = scope; } public TypeReference(string @namespace, string name, ModuleDefinition module, IMetadataScope scope, bool valueType) : this(@namespace, name, module, scope) { value_type = valueType; } public virtual TypeReference GetElementType() { return this; } public virtual TypeDefinition Resolve() { var module = this.Module; if (module == null) throw new NotSupportedException(); return module.Resolve(this); } } static partial class Mixin { public static bool IsPrimitive(ElementType self) { switch (self) { case ElementType.Boolean: case ElementType.Char: case ElementType.I: case ElementType.U: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: return true; default: return false; } } public static bool IsTypeOf(TypeReference self, string @namespace, string name) { return self.Name == name && self.Namespace == @namespace; } public static bool IsTypeSpecification(TypeReference type) { switch (type.etype) { case ElementType.Array: case ElementType.ByRef: case ElementType.CModOpt: case ElementType.CModReqD: case ElementType.FnPtr: case ElementType.GenericInst: case ElementType.MVar: case ElementType.Pinned: case ElementType.Ptr: case ElementType.SzArray: case ElementType.Sentinel: case ElementType.Var: return true; } return false; } public static TypeDefinition CheckedResolve(TypeReference self) { var type = self.Resolve(); if (type == null) throw new ResolutionException(self); return type; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/TypeSpecification.cs ================================================ // // TypeSpecification.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.Metadata; namespace Mono.Cecil { public abstract class TypeSpecification : TypeReference { readonly TypeReference element_type; public TypeReference ElementType { get { return element_type; } } public override string Name { get { return element_type.Name; } set { throw new NotSupportedException (); } } public override string Namespace { get { return element_type.Namespace; } set { throw new NotSupportedException (); } } public override IMetadataScope Scope { get { return element_type.Scope; } } public override ModuleDefinition Module { get { return element_type.Module; } } public override string FullName { get { return element_type.FullName; } } internal override bool ContainsGenericParameter { get { return element_type.ContainsGenericParameter; } } public override MetadataType MetadataType { get { return (MetadataType) etype; } } internal TypeSpecification (TypeReference type) : base (null, null) { this.element_type = type; this.token = new MetadataToken (TokenType.TypeSpec); } public override TypeReference GetElementType () { return element_type; } } static partial class Mixin { public static void CheckType (TypeReference type) { if (type == null) throw new ArgumentNullException ("type"); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/TypeSystem.cs ================================================ // // TypeSystem.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.Metadata; namespace Mono.Cecil { public abstract class TypeSystem { sealed class CoreTypeSystem : TypeSystem { public CoreTypeSystem(ModuleDefinition module) : base(module) { } internal override TypeReference LookupType(string @namespace, string name) { var type = LookupTypeDefinition(@namespace, name) ?? LookupTypeForwarded(@namespace, name); if (type != null) return type; throw new NotSupportedException(); } TypeReference LookupTypeDefinition(string @namespace, string name) { var metadata = module.MetadataSystem; if (metadata.Types == null) Initialize(module.Types); return module.Read(new Row(@namespace, name), (row, reader) => { var types = reader.metadata.Types; for (int i = 0; i < types.Length; i++) { if (types[i] == null) types[i] = reader.GetTypeDefinition((uint)i + 1); var type = types[i]; if (type.Name == row.Col2 && type.Namespace == row.Col1) return type; } return null; }); } TypeReference LookupTypeForwarded(string @namespace, string name) { if (!module.HasExportedTypes) return null; var exported_types = module.ExportedTypes; for (int i = 0; i < exported_types.Count; i++) { var exported_type = exported_types[i]; if (exported_type.Name == name && exported_type.Namespace == @namespace) return exported_type.CreateReference(); } return null; } static void Initialize(object obj) { } } sealed class CommonTypeSystem : TypeSystem { AssemblyNameReference corlib; public CommonTypeSystem(ModuleDefinition module) : base(module) { } internal override TypeReference LookupType(string @namespace, string name) { return CreateTypeReference(@namespace, name); } public AssemblyNameReference GetCorlibReference() { if (corlib != null) return corlib; const string mscorlib = "mscorlib"; const string systemruntime = "System.Runtime"; var references = module.AssemblyReferences; for (int i = 0; i < references.Count; i++) { var reference = references[i]; if (reference.Name == mscorlib || reference.Name == systemruntime) return corlib = reference; } corlib = new AssemblyNameReference { Name = mscorlib, Version = GetCorlibVersion(), PublicKeyToken = new byte[] { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 }, }; references.Add(corlib); return corlib; } Version GetCorlibVersion() { switch (module.Runtime) { case TargetRuntime.Net_1_0: case TargetRuntime.Net_1_1: return new Version(1, 0, 0, 0); case TargetRuntime.Net_2_0: return new Version(2, 0, 0, 0); case TargetRuntime.Net_4_0: return new Version(4, 0, 0, 0); default: throw new NotSupportedException(); } } TypeReference CreateTypeReference(string @namespace, string name) { return new TypeReference(@namespace, name, module, GetCorlibReference()); } } readonly ModuleDefinition module; TypeReference type_object; TypeReference type_void; TypeReference type_bool; TypeReference type_char; TypeReference type_sbyte; TypeReference type_byte; TypeReference type_int16; TypeReference type_uint16; TypeReference type_int32; TypeReference type_uint32; TypeReference type_int64; TypeReference type_uint64; TypeReference type_single; TypeReference type_double; TypeReference type_intptr; TypeReference type_uintptr; TypeReference type_string; TypeReference type_typedref; TypeSystem(ModuleDefinition module) { this.module = module; } internal static TypeSystem CreateTypeSystem(ModuleDefinition module) { if (Mixin.IsCorlib(module)) return new CoreTypeSystem(module); return new CommonTypeSystem(module); } internal abstract TypeReference LookupType(string @namespace, string name); TypeReference LookupSystemType(ref TypeReference typeRef, string name, ElementType element_type) { lock (module.SyncRoot) { if (typeRef != null) return typeRef; var type = LookupType("System", name); type.etype = element_type; return typeRef = type; } } TypeReference LookupSystemValueType(ref TypeReference typeRef, string name, ElementType element_type) { lock (module.SyncRoot) { if (typeRef != null) return typeRef; var type = LookupType("System", name); type.etype = element_type; type.IsValueType = true; return typeRef = type; } } public IMetadataScope Corlib { get { var common = this as CommonTypeSystem; if (common == null) return module; return common.GetCorlibReference(); } } public TypeReference Object { get { return type_object ?? (LookupSystemType(ref type_object, "Object", ElementType.Object)); } } public TypeReference Void { get { return type_void ?? (LookupSystemType(ref type_void, "Void", ElementType.Void)); } } public TypeReference Boolean { get { return type_bool ?? (LookupSystemValueType(ref type_bool, "Boolean", ElementType.Boolean)); } } public TypeReference Char { get { return type_char ?? (LookupSystemValueType(ref type_char, "Char", ElementType.Char)); } } public TypeReference SByte { get { return type_sbyte ?? (LookupSystemValueType(ref type_sbyte, "SByte", ElementType.I1)); } } public TypeReference Byte { get { return type_byte ?? (LookupSystemValueType(ref type_byte, "Byte", ElementType.U1)); } } public TypeReference Int16 { get { return type_int16 ?? (LookupSystemValueType(ref type_int16, "Int16", ElementType.I2)); } } public TypeReference UInt16 { get { return type_uint16 ?? (LookupSystemValueType(ref type_uint16, "UInt16", ElementType.U2)); } } public TypeReference Int32 { get { return type_int32 ?? (LookupSystemValueType(ref type_int32, "Int32", ElementType.I4)); } } public TypeReference UInt32 { get { return type_uint32 ?? (LookupSystemValueType(ref type_uint32, "UInt32", ElementType.U4)); } } public TypeReference Int64 { get { return type_int64 ?? (LookupSystemValueType(ref type_int64, "Int64", ElementType.I8)); } } public TypeReference UInt64 { get { return type_uint64 ?? (LookupSystemValueType(ref type_uint64, "UInt64", ElementType.U8)); } } public TypeReference Single { get { return type_single ?? (LookupSystemValueType(ref type_single, "Single", ElementType.R4)); } } public TypeReference Double { get { return type_double ?? (LookupSystemValueType(ref type_double, "Double", ElementType.R8)); } } public TypeReference IntPtr { get { return type_intptr ?? (LookupSystemValueType(ref type_intptr, "IntPtr", ElementType.I)); } } public TypeReference UIntPtr { get { return type_uintptr ?? (LookupSystemValueType(ref type_uintptr, "UIntPtr", ElementType.U)); } } public TypeReference String { get { return type_string ?? (LookupSystemType(ref type_string, "String", ElementType.String)); } } public TypeReference TypedReference { get { return type_typedref ?? (LookupSystemValueType(ref type_typedref, "TypedReference", ElementType.TypedByRef)); } } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil/VariantType.cs ================================================ // // VariantType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public enum VariantType { None = 0, I2 = 2, I4 = 3, R4 = 4, R8 = 5, CY = 6, Date = 7, BStr = 8, Dispatch = 9, Error = 10, Bool = 11, Variant = 12, Unknown = 13, Decimal = 14, I1 = 16, UI1 = 17, UI2 = 18, UI4 = 19, Int = 22, UInt = 23 } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/Code.cs ================================================ // // Code.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil.Cil { public enum Code { Nop, Break, Ldarg_0, Ldarg_1, Ldarg_2, Ldarg_3, Ldloc_0, Ldloc_1, Ldloc_2, Ldloc_3, Stloc_0, Stloc_1, Stloc_2, Stloc_3, Ldarg_S, Ldarga_S, Starg_S, Ldloc_S, Ldloca_S, Stloc_S, Ldnull, Ldc_I4_M1, Ldc_I4_0, Ldc_I4_1, Ldc_I4_2, Ldc_I4_3, Ldc_I4_4, Ldc_I4_5, Ldc_I4_6, Ldc_I4_7, Ldc_I4_8, Ldc_I4_S, Ldc_I4, Ldc_I8, Ldc_R4, Ldc_R8, Dup, Pop, Jmp, Call, Calli, Ret, Br_S, Brfalse_S, Brtrue_S, Beq_S, Bge_S, Bgt_S, Ble_S, Blt_S, Bne_Un_S, Bge_Un_S, Bgt_Un_S, Ble_Un_S, Blt_Un_S, Br, Brfalse, Brtrue, Beq, Bge, Bgt, Ble, Blt, Bne_Un, Bge_Un, Bgt_Un, Ble_Un, Blt_Un, Switch, Ldind_I1, Ldind_U1, Ldind_I2, Ldind_U2, Ldind_I4, Ldind_U4, Ldind_I8, Ldind_I, Ldind_R4, Ldind_R8, Ldind_Ref, Stind_Ref, Stind_I1, Stind_I2, Stind_I4, Stind_I8, Stind_R4, Stind_R8, Add, Sub, Mul, Div, Div_Un, Rem, Rem_Un, And, Or, Xor, Shl, Shr, Shr_Un, Neg, Not, Conv_I1, Conv_I2, Conv_I4, Conv_I8, Conv_R4, Conv_R8, Conv_U4, Conv_U8, Callvirt, Cpobj, Ldobj, Ldstr, Newobj, Castclass, Isinst, Conv_R_Un, Unbox, Throw, Ldfld, Ldflda, Stfld, Ldsfld, Ldsflda, Stsfld, Stobj, Conv_Ovf_I1_Un, Conv_Ovf_I2_Un, Conv_Ovf_I4_Un, Conv_Ovf_I8_Un, Conv_Ovf_U1_Un, Conv_Ovf_U2_Un, Conv_Ovf_U4_Un, Conv_Ovf_U8_Un, Conv_Ovf_I_Un, Conv_Ovf_U_Un, Box, Newarr, Ldlen, Ldelema, Ldelem_I1, Ldelem_U1, Ldelem_I2, Ldelem_U2, Ldelem_I4, Ldelem_U4, Ldelem_I8, Ldelem_I, Ldelem_R4, Ldelem_R8, Ldelem_Ref, Stelem_I, Stelem_I1, Stelem_I2, Stelem_I4, Stelem_I8, Stelem_R4, Stelem_R8, Stelem_Ref, Ldelem_Any, Stelem_Any, Unbox_Any, Conv_Ovf_I1, Conv_Ovf_U1, Conv_Ovf_I2, Conv_Ovf_U2, Conv_Ovf_I4, Conv_Ovf_U4, Conv_Ovf_I8, Conv_Ovf_U8, Refanyval, Ckfinite, Mkrefany, Ldtoken, Conv_U2, Conv_U1, Conv_I, Conv_Ovf_I, Conv_Ovf_U, Add_Ovf, Add_Ovf_Un, Mul_Ovf, Mul_Ovf_Un, Sub_Ovf, Sub_Ovf_Un, Endfinally, Leave, Leave_S, Stind_I, Conv_U, Arglist, Ceq, Cgt, Cgt_Un, Clt, Clt_Un, Ldftn, Ldvirtftn, Ldarg, Ldarga, Starg, Ldloc, Ldloca, Stloc, Localloc, Endfilter, Unaligned, Volatile, Tail, Initobj, Constrained, Cpblk, Initblk, No, Rethrow, Sizeof, Refanytype, Readonly, } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/CodeReader.cs ================================================ // // CodeReader.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.PE; using Mono.Collections.Generic; using RVA = System.UInt32; namespace Mono.Cecil.Cil { sealed class CodeReader : ByteBuffer { readonly internal MetadataReader reader; int start; Section code_section; MethodDefinition method; MethodBody body; int Offset { get { return base.position - start; } } public CodeReader(Section section, MetadataReader reader) : base(section.Data) { this.code_section = section; this.reader = reader; } public MethodBody ReadMethodBody(MethodDefinition method) { this.method = method; this.body = new MethodBody(method); reader.context = method; ReadMethodBody(); return this.body; } public void MoveTo(int rva) { if (!IsInSection(rva)) { code_section = reader.image.GetSectionAtVirtualAddress((uint)rva); Reset(code_section.Data); } base.position = rva - (int)code_section.VirtualAddress; } bool IsInSection(int rva) { return code_section.VirtualAddress <= rva && rva < code_section.VirtualAddress + code_section.SizeOfRawData; } void ReadMethodBody() { MoveTo(method.RVA); var flags = ReadByte(); switch (flags & 0x3) { case 0x2: // tiny body.code_size = flags >> 2; body.MaxStackSize = 8; ReadCode(); break; case 0x3: // fat base.position--; ReadFatMethod(); break; default: throw new InvalidOperationException(); } var symbol_reader = reader.module.symbol_reader; if (symbol_reader != null) { var instructions = body.Instructions; symbol_reader.Read(body, offset => GetInstruction(instructions, offset)); } } void ReadFatMethod() { var flags = ReadUInt16(); body.max_stack_size = ReadUInt16(); body.code_size = (int)ReadUInt32(); body.local_var_token = new MetadataToken(ReadUInt32()); body.init_locals = (flags & 0x10) != 0; if (body.local_var_token.RID != 0) body.variables = ReadVariables(body.local_var_token); ReadCode(); if ((flags & 0x8) != 0) ReadSection(); } public VariableDefinitionCollection ReadVariables(MetadataToken local_var_token) { var position = reader.position; var variables = reader.ReadVariables(local_var_token); reader.position = position; return variables; } void ReadCode() { start = position; var code_size = body.code_size; if (code_size < 0 || buffer.Length <= (uint)(code_size + position)) code_size = 0; var end = start + code_size; var instructions = body.instructions = new InstructionCollection((code_size + 1) / 2); while (position < end) { var offset = base.position - start; var opcode = ReadOpCode(); var current = new Instruction(offset, opcode); if (opcode.OperandType != OperandType.InlineNone) current.operand = ReadOperand(current); instructions.Add(current); } ResolveBranches(instructions); } OpCode ReadOpCode() { var il_opcode = ReadByte(); return il_opcode != 0xfe ? OpCodes.OneByteOpCode[il_opcode] : OpCodes.TwoBytesOpCode[ReadByte()]; } object ReadOperand(Instruction instruction) { switch (instruction.opcode.OperandType) { case OperandType.InlineSwitch: var length = ReadInt32(); var base_offset = Offset + (4 * length); var branches = new int[length]; for (int i = 0; i < length; i++) branches[i] = base_offset + ReadInt32(); return branches; case OperandType.ShortInlineBrTarget: return ReadSByte() + Offset; case OperandType.InlineBrTarget: return ReadInt32() + Offset; case OperandType.ShortInlineI: if (instruction.opcode == OpCodes.Ldc_I4_S) return ReadSByte(); return ReadByte(); case OperandType.InlineI: return ReadInt32(); case OperandType.ShortInlineR: return ReadSingle(); case OperandType.InlineR: return ReadDouble(); case OperandType.InlineI8: return ReadInt64(); case OperandType.ShortInlineVar: return GetVariable(ReadByte()); case OperandType.InlineVar: return GetVariable(ReadUInt16()); case OperandType.ShortInlineArg: return GetParameter(ReadByte()); case OperandType.InlineArg: return GetParameter(ReadUInt16()); case OperandType.InlineSig: return GetCallSite(ReadToken()); case OperandType.InlineString: return GetString(ReadToken()); case OperandType.InlineTok: case OperandType.InlineType: case OperandType.InlineMethod: case OperandType.InlineField: return reader.LookupToken(ReadToken()); default: throw new NotSupportedException(); } } public string GetString(MetadataToken token) { return reader.image.UserStringHeap.Read(token.RID); } public ParameterDefinition GetParameter(int index) { return Mixin.GetParameter(body, index); } public VariableDefinition GetVariable(int index) { return Mixin.GetVariable(body, index); } public CallSite GetCallSite(MetadataToken token) { return reader.ReadCallSite(token); } void ResolveBranches(Collection instructions) { var items = instructions.items; var size = instructions.size; for (int i = 0; i < size; i++) { var instruction = items[i]; switch (instruction.opcode.OperandType) { case OperandType.ShortInlineBrTarget: case OperandType.InlineBrTarget: instruction.operand = GetInstruction((int)instruction.operand); break; case OperandType.InlineSwitch: var offsets = (int[])instruction.operand; var branches = new Instruction[offsets.Length]; for (int j = 0; j < offsets.Length; j++) branches[j] = GetInstruction(offsets[j]); instruction.operand = branches; break; } } } Instruction GetInstruction(int offset) { return GetInstruction(body.Instructions, offset); } static Instruction GetInstruction(Collection instructions, int offset) { var size = instructions.size; var items = instructions.items; if (offset < 0 || offset > items[size - 1].offset) return null; int min = 0; int max = size - 1; while (min <= max) { int mid = min + ((max - min) / 2); var instruction = items[mid]; var instruction_offset = instruction.offset; if (offset == instruction_offset) return instruction; if (offset < instruction_offset) max = mid - 1; else min = mid + 1; } return null; } void ReadSection() { Align(4); const byte fat_format = 0x40; const byte more_sects = 0x80; var flags = ReadByte(); if ((flags & fat_format) == 0) ReadSmallSection(); else ReadFatSection(); if ((flags & more_sects) != 0) ReadSection(); } void ReadSmallSection() { var count = ReadByte() / 12; Advance(2); ReadExceptionHandlers( count, () => (int)ReadUInt16(), () => (int)ReadByte()); } void ReadFatSection() { position--; var count = (ReadInt32() >> 8) / 24; ReadExceptionHandlers( count, ReadInt32, ReadInt32); } // inline ? void ReadExceptionHandlers(int count, Func read_entry, Func read_length) { for (int i = 0; i < count; i++) { var handler = new ExceptionHandler( (ExceptionHandlerType)(read_entry() & 0x7)); handler.TryStart = GetInstruction(read_entry()); handler.TryEnd = GetInstruction(handler.TryStart.Offset + read_length()); handler.HandlerStart = GetInstruction(read_entry()); handler.HandlerEnd = GetInstruction(handler.HandlerStart.Offset + read_length()); ReadExceptionHandlerSpecific(handler); this.body.ExceptionHandlers.Add(handler); } } void ReadExceptionHandlerSpecific(ExceptionHandler handler) { switch (handler.HandlerType) { case ExceptionHandlerType.Catch: handler.CatchType = (TypeReference)reader.LookupToken(ReadToken()); break; case ExceptionHandlerType.Filter: handler.FilterStart = GetInstruction(ReadInt32()); break; default: Advance(4); break; } } void Align(int align) { align--; Advance(((position + align) & ~align) - position); } public MetadataToken ReadToken() { return new MetadataToken(ReadUInt32()); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/CodeWriter.cs ================================================ // // CodeWriter.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using Mono.Collections.Generic; using Mono.Cecil.Metadata; using Mono.Cecil.PE; using RVA = System.UInt32; ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/Document.cs ================================================ // // Document.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil.Cil { public enum DocumentType { Other, Text, } public enum DocumentHashAlgorithm { None, MD5, SHA1, } public enum DocumentLanguage { Other, C, Cpp, CSharp, Basic, Java, Cobol, Pascal, Cil, JScript, Smc, MCpp, FSharp, } public enum DocumentLanguageVendor { Other, Microsoft, } public sealed class Document { string url; byte type; byte hash_algorithm; byte language; byte language_vendor; byte [] hash; public string Url { get { return url; } set { url = value; } } public DocumentType Type { get { return (DocumentType) type; } set { type = (byte) value; } } public DocumentHashAlgorithm HashAlgorithm { get { return (DocumentHashAlgorithm) hash_algorithm; } set { hash_algorithm = (byte) value; } } public DocumentLanguage Language { get { return (DocumentLanguage) language; } set { language = (byte) value; } } public DocumentLanguageVendor LanguageVendor { get { return (DocumentLanguageVendor) language_vendor; } set { language_vendor = (byte) value; } } public byte [] Hash { get { return hash; } set { hash = value; } } public Document (string url) { this.url = url; this.hash = Empty.Array; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/ExceptionHandler.cs ================================================ // // ExceptionHandler.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil.Cil { public enum ExceptionHandlerType { Catch = 0, Filter = 1, Finally = 2, Fault = 4, } public sealed class ExceptionHandler { Instruction try_start; Instruction try_end; Instruction filter_start; Instruction handler_start; Instruction handler_end; TypeReference catch_type; ExceptionHandlerType handler_type; public Instruction TryStart { get { return try_start; } set { try_start = value; } } public Instruction TryEnd { get { return try_end; } set { try_end = value; } } public Instruction FilterStart { get { return filter_start; } set { filter_start = value; } } public Instruction HandlerStart { get { return handler_start; } set { handler_start = value; } } public Instruction HandlerEnd { get { return handler_end; } set { handler_end = value; } } public TypeReference CatchType { get { return catch_type; } set { catch_type = value; } } public ExceptionHandlerType HandlerType { get { return handler_type; } set { handler_type = value; } } public ExceptionHandler (ExceptionHandlerType handlerType) { this.handler_type = handlerType; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/ILProcessor.cs ================================================ // // ILProcessor.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Collections.Generic; namespace Mono.Cecil.Cil { public sealed class ILProcessor { readonly MethodBody body; readonly Collection instructions; public MethodBody Body { get { return body; } } internal ILProcessor (MethodBody body) { this.body = body; this.instructions = body.Instructions; } public Instruction Create (OpCode opcode) { return Instruction.Create (opcode); } public Instruction Create (OpCode opcode, TypeReference type) { return Instruction.Create (opcode, type); } public Instruction Create (OpCode opcode, CallSite site) { return Instruction.Create (opcode, site); } public Instruction Create (OpCode opcode, MethodReference method) { return Instruction.Create (opcode, method); } public Instruction Create (OpCode opcode, FieldReference field) { return Instruction.Create (opcode, field); } public Instruction Create (OpCode opcode, string value) { return Instruction.Create (opcode, value); } public Instruction Create (OpCode opcode, sbyte value) { return Instruction.Create (opcode, value); } public Instruction Create (OpCode opcode, byte value) { if (opcode.OperandType == OperandType.ShortInlineVar) return Instruction.Create (opcode, body.Variables [value]); if (opcode.OperandType == OperandType.ShortInlineArg) return Instruction.Create (opcode, Mixin.GetParameter (body,value)); return Instruction.Create (opcode, value); } public Instruction Create (OpCode opcode, int value) { if (opcode.OperandType == OperandType.InlineVar) return Instruction.Create (opcode, body.Variables [value]); if (opcode.OperandType == OperandType.InlineArg) return Instruction.Create (opcode, Mixin.GetParameter (body,value)); return Instruction.Create (opcode, value); } public Instruction Create (OpCode opcode, long value) { return Instruction.Create (opcode, value); } public Instruction Create (OpCode opcode, float value) { return Instruction.Create (opcode, value); } public Instruction Create (OpCode opcode, double value) { return Instruction.Create (opcode, value); } public Instruction Create (OpCode opcode, Instruction target) { return Instruction.Create (opcode, target); } public Instruction Create (OpCode opcode, Instruction [] targets) { return Instruction.Create (opcode, targets); } public Instruction Create (OpCode opcode, VariableDefinition variable) { return Instruction.Create (opcode, variable); } public Instruction Create (OpCode opcode, ParameterDefinition parameter) { return Instruction.Create (opcode, parameter); } public void Emit (OpCode opcode) { Append (Create (opcode)); } public void Emit (OpCode opcode, TypeReference type) { Append (Create (opcode, type)); } public void Emit (OpCode opcode, MethodReference method) { Append (Create (opcode, method)); } public void Emit (OpCode opcode, CallSite site) { Append (Create (opcode, site)); } public void Emit (OpCode opcode, FieldReference field) { Append (Create (opcode, field)); } public void Emit (OpCode opcode, string value) { Append (Create (opcode, value)); } public void Emit (OpCode opcode, byte value) { Append (Create (opcode, value)); } public void Emit (OpCode opcode, sbyte value) { Append (Create (opcode, value)); } public void Emit (OpCode opcode, int value) { Append (Create (opcode, value)); } public void Emit (OpCode opcode, long value) { Append (Create (opcode, value)); } public void Emit (OpCode opcode, float value) { Append (Create (opcode, value)); } public void Emit (OpCode opcode, double value) { Append (Create (opcode, value)); } public void Emit (OpCode opcode, Instruction target) { Append (Create (opcode, target)); } public void Emit (OpCode opcode, Instruction [] targets) { Append (Create (opcode, targets)); } public void Emit (OpCode opcode, VariableDefinition variable) { Append (Create (opcode, variable)); } public void Emit (OpCode opcode, ParameterDefinition parameter) { Append (Create (opcode, parameter)); } public void InsertBefore (Instruction target, Instruction instruction) { if (target == null) throw new ArgumentNullException ("target"); if (instruction == null) throw new ArgumentNullException ("instruction"); var index = instructions.IndexOf (target); if (index == -1) throw new ArgumentOutOfRangeException ("target"); instructions.Insert (index, instruction); } public void InsertAfter (Instruction target, Instruction instruction) { if (target == null) throw new ArgumentNullException ("target"); if (instruction == null) throw new ArgumentNullException ("instruction"); var index = instructions.IndexOf (target); if (index == -1) throw new ArgumentOutOfRangeException ("target"); instructions.Insert (index + 1, instruction); } public void Append (Instruction instruction) { if (instruction == null) throw new ArgumentNullException ("instruction"); instructions.Add (instruction); } public void Replace (Instruction target, Instruction instruction) { if (target == null) throw new ArgumentNullException ("target"); if (instruction == null) throw new ArgumentNullException ("instruction"); InsertAfter (target, instruction); Remove (target); } public void Remove (Instruction instruction) { if (instruction == null) throw new ArgumentNullException ("instruction"); if (!instructions.Remove (instruction)) throw new ArgumentOutOfRangeException ("instruction"); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/Instruction.cs ================================================ // // Instruction.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Text; namespace Mono.Cecil.Cil { public sealed class Instruction { internal int offset; internal OpCode opcode; internal object operand; internal Instruction previous; internal Instruction next; SequencePoint sequence_point; public int Offset { get { return offset; } set { offset = value; } } public OpCode OpCode { get { return opcode; } set { opcode = value; } } public object Operand { get { return operand; } set { operand = value; } } public Instruction Previous { get { return previous; } set { previous = value; } } public Instruction Next { get { return next; } set { next = value; } } public SequencePoint SequencePoint { get { return sequence_point; } set { sequence_point = value; } } internal Instruction (int offset, OpCode opCode) { this.offset = offset; this.opcode = opCode; } internal Instruction (OpCode opcode, object operand) { this.opcode = opcode; this.operand = operand; } public int GetSize () { int size = opcode.Size; switch (opcode.OperandType) { case OperandType.InlineSwitch: return size + (1 + ((Instruction []) operand).Length) * 4; case OperandType.InlineI8: case OperandType.InlineR: return size + 8; case OperandType.InlineBrTarget: case OperandType.InlineField: case OperandType.InlineI: case OperandType.InlineMethod: case OperandType.InlineString: case OperandType.InlineTok: case OperandType.InlineType: case OperandType.ShortInlineR: case OperandType.InlineSig: return size + 4; case OperandType.InlineArg: case OperandType.InlineVar: return size + 2; case OperandType.ShortInlineBrTarget: case OperandType.ShortInlineI: case OperandType.ShortInlineArg: case OperandType.ShortInlineVar: return size + 1; default: return size; } } public override string ToString () { var instruction = new StringBuilder (); AppendLabel (instruction, this); instruction.Append (':'); instruction.Append (' '); instruction.Append (opcode.Name); if (operand == null) return instruction.ToString (); instruction.Append (' '); switch (opcode.OperandType) { case OperandType.ShortInlineBrTarget: case OperandType.InlineBrTarget: AppendLabel (instruction, (Instruction) operand); break; case OperandType.InlineSwitch: var labels = (Instruction []) operand; for (int i = 0; i < labels.Length; i++) { if (i > 0) instruction.Append (','); AppendLabel (instruction, labels [i]); } break; case OperandType.InlineString: instruction.Append ('\"'); instruction.Append (operand); instruction.Append ('\"'); break; default: instruction.Append (operand); break; } return instruction.ToString (); } static void AppendLabel (StringBuilder builder, Instruction instruction) { builder.Append ("IL_"); builder.Append (instruction.offset.ToString ("x4")); } public static Instruction Create (OpCode opcode) { if (opcode.OperandType != OperandType.InlineNone) throw new ArgumentException ("opcode"); return new Instruction (opcode, null); } public static Instruction Create (OpCode opcode, TypeReference type) { if (type == null) throw new ArgumentNullException ("type"); if (opcode.OperandType != OperandType.InlineType && opcode.OperandType != OperandType.InlineTok) throw new ArgumentException ("opcode"); return new Instruction (opcode, type); } public static Instruction Create (OpCode opcode, CallSite site) { if (site == null) throw new ArgumentNullException ("site"); if (opcode.Code != Code.Calli) throw new ArgumentException ("code"); return new Instruction (opcode, site); } public static Instruction Create (OpCode opcode, MethodReference method) { if (method == null) throw new ArgumentNullException ("method"); if (opcode.OperandType != OperandType.InlineMethod && opcode.OperandType != OperandType.InlineTok) throw new ArgumentException ("opcode"); return new Instruction (opcode, method); } public static Instruction Create (OpCode opcode, FieldReference field) { if (field == null) throw new ArgumentNullException ("field"); if (opcode.OperandType != OperandType.InlineField && opcode.OperandType != OperandType.InlineTok) throw new ArgumentException ("opcode"); return new Instruction (opcode, field); } public static Instruction Create (OpCode opcode, string value) { if (value == null) throw new ArgumentNullException ("value"); if (opcode.OperandType != OperandType.InlineString) throw new ArgumentException ("opcode"); return new Instruction (opcode, value); } public static Instruction Create (OpCode opcode, sbyte value) { if (opcode.OperandType != OperandType.ShortInlineI && opcode != OpCodes.Ldc_I4_S) throw new ArgumentException ("opcode"); return new Instruction (opcode, value); } public static Instruction Create (OpCode opcode, byte value) { if (opcode.OperandType != OperandType.ShortInlineI || opcode == OpCodes.Ldc_I4_S) throw new ArgumentException ("opcode"); return new Instruction (opcode, value); } public static Instruction Create (OpCode opcode, int value) { if (opcode.OperandType != OperandType.InlineI) throw new ArgumentException ("opcode"); return new Instruction (opcode, value); } public static Instruction Create (OpCode opcode, long value) { if (opcode.OperandType != OperandType.InlineI8) throw new ArgumentException ("opcode"); return new Instruction (opcode, value); } public static Instruction Create (OpCode opcode, float value) { if (opcode.OperandType != OperandType.ShortInlineR) throw new ArgumentException ("opcode"); return new Instruction (opcode, value); } public static Instruction Create (OpCode opcode, double value) { if (opcode.OperandType != OperandType.InlineR) throw new ArgumentException ("opcode"); return new Instruction (opcode, value); } public static Instruction Create (OpCode opcode, Instruction target) { if (target == null) throw new ArgumentNullException ("target"); if (opcode.OperandType != OperandType.InlineBrTarget && opcode.OperandType != OperandType.ShortInlineBrTarget) throw new ArgumentException ("opcode"); return new Instruction (opcode, target); } public static Instruction Create (OpCode opcode, Instruction [] targets) { if (targets == null) throw new ArgumentNullException ("targets"); if (opcode.OperandType != OperandType.InlineSwitch) throw new ArgumentException ("opcode"); return new Instruction (opcode, targets); } public static Instruction Create (OpCode opcode, VariableDefinition variable) { if (variable == null) throw new ArgumentNullException ("variable"); if (opcode.OperandType != OperandType.ShortInlineVar && opcode.OperandType != OperandType.InlineVar) throw new ArgumentException ("opcode"); return new Instruction (opcode, variable); } public static Instruction Create (OpCode opcode, ParameterDefinition parameter) { if (parameter == null) throw new ArgumentNullException ("parameter"); if (opcode.OperandType != OperandType.ShortInlineArg && opcode.OperandType != OperandType.InlineArg) throw new ArgumentException ("opcode"); return new Instruction (opcode, parameter); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/MethodBody.cs ================================================ // // MethodBody.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Threading; using Mono.Collections.Generic; namespace Mono.Cecil.Cil { public sealed class MethodBody : IVariableDefinitionProvider { readonly internal MethodDefinition method; internal ParameterDefinition this_parameter; internal int max_stack_size; internal int code_size; internal bool init_locals; internal MetadataToken local_var_token; internal Collection instructions; internal Collection exceptions; internal Collection variables; Scope scope; public MethodDefinition Method { get { return method; } } public int MaxStackSize { get { return max_stack_size; } set { max_stack_size = value; } } public int CodeSize { get { return code_size; } } public bool InitLocals { get { return init_locals; } set { init_locals = value; } } public MetadataToken LocalVarToken { get { return local_var_token; } set { local_var_token = value; } } public Collection Instructions { get { return instructions ?? (instructions = new InstructionCollection()); } } public bool HasExceptionHandlers { get { return !Mixin.IsNullOrEmpty(exceptions); } } public Collection ExceptionHandlers { get { return exceptions ?? (exceptions = new Collection()); } } public bool HasVariables { get { return !Mixin.IsNullOrEmpty(variables); } } public Collection Variables { get { return variables ?? (variables = new VariableDefinitionCollection()); } } public Scope Scope { get { return scope; } set { scope = value; } } public ParameterDefinition ThisParameter { get { if (method == null || method.DeclaringType == null) throw new NotSupportedException(); if (!method.HasThis) return null; if (this_parameter == null) this_parameter = ThisParameterFor(method); return this_parameter; } } static ParameterDefinition ThisParameterFor(MethodDefinition method) { var declaring_type = method.DeclaringType; var type = declaring_type.IsValueType || declaring_type.IsPrimitive ? new PointerType(declaring_type) : declaring_type as TypeReference; return new ParameterDefinition(type, method); } public MethodBody(MethodDefinition method) { this.method = method; } public ILProcessor GetILProcessor() { return new ILProcessor(this); } } public interface IVariableDefinitionProvider { bool HasVariables { get; } Collection Variables { get; } } class VariableDefinitionCollection : Collection { internal VariableDefinitionCollection() { } internal VariableDefinitionCollection(int capacity) : base(capacity) { } protected override void OnAdd(VariableDefinition item, int index) { item.index = index; } protected override void OnInsert(VariableDefinition item, int index) { item.index = index; for (int i = index; i < size; i++) items[i].index = i + 1; } protected override void OnSet(VariableDefinition item, int index) { item.index = index; } protected override void OnRemove(VariableDefinition item, int index) { item.index = -1; for (int i = index + 1; i < size; i++) items[i].index = i - 1; } } class InstructionCollection : Collection { internal InstructionCollection() { } internal InstructionCollection(int capacity) : base(capacity) { } protected override void OnAdd(Instruction item, int index) { if (index == 0) return; var previous = items[index - 1]; previous.next = item; item.previous = previous; } protected override void OnInsert(Instruction item, int index) { if (size == 0) return; var current = items[index]; if (current == null) { var last = items[index - 1]; last.next = item; item.previous = last; return; } var previous = current.previous; if (previous != null) { previous.next = item; item.previous = previous; } current.previous = item; item.next = current; } protected override void OnSet(Instruction item, int index) { var current = items[index]; item.previous = current.previous; item.next = current.next; current.previous = null; current.next = null; } protected override void OnRemove(Instruction item, int index) { var previous = item.previous; if (previous != null) previous.next = item.next; var next = item.next; if (next != null) next.previous = item.previous; item.previous = null; item.next = null; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/OpCode.cs ================================================ // // OpCode.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil.Cil { public enum FlowControl { Branch, Break, Call, Cond_Branch, Meta, Next, Phi, Return, Throw, } public enum OpCodeType { Annotation, Macro, Nternal, Objmodel, Prefix, Primitive, } public enum OperandType { InlineBrTarget, InlineField, InlineI, InlineI8, InlineMethod, InlineNone, InlinePhi, InlineR, InlineSig, InlineString, InlineSwitch, InlineTok, InlineType, InlineVar, InlineArg, ShortInlineBrTarget, ShortInlineI, ShortInlineR, ShortInlineVar, ShortInlineArg, } public enum StackBehaviour { Pop0, Pop1, Pop1_pop1, Popi, Popi_pop1, Popi_popi, Popi_popi8, Popi_popi_popi, Popi_popr4, Popi_popr8, Popref, Popref_pop1, Popref_popi, Popref_popi_popi, Popref_popi_popi8, Popref_popi_popr4, Popref_popi_popr8, Popref_popi_popref, PopAll, Push0, Push1, Push1_push1, Pushi, Pushi8, Pushr4, Pushr8, Pushref, Varpop, Varpush, } public struct OpCode { readonly byte op1; readonly byte op2; readonly byte code; readonly byte flow_control; readonly byte opcode_type; readonly byte operand_type; readonly byte stack_behavior_pop; readonly byte stack_behavior_push; public string Name { get { return OpCodeNames.names [(int) Code]; } } public int Size { get { return op1 == 0xff ? 1 : 2; } } public byte Op1 { get { return op1; } } public byte Op2 { get { return op2; } } public short Value { get { return op1 == 0xff ? op2 : (short) ((op1 << 8) | op2); } } public Code Code { get { return (Code) code; } } public FlowControl FlowControl { get { return (FlowControl) flow_control; } } public OpCodeType OpCodeType { get { return (OpCodeType) opcode_type; } } public OperandType OperandType { get { return (OperandType) operand_type; } } public StackBehaviour StackBehaviourPop { get { return (StackBehaviour) stack_behavior_pop; } } public StackBehaviour StackBehaviourPush { get { return (StackBehaviour) stack_behavior_push; } } internal OpCode (int x, int y) { this.op1 = (byte) ((x >> 0) & 0xff); this.op2 = (byte) ((x >> 8) & 0xff); this.code = (byte) ((x >> 16) & 0xff); this.flow_control = (byte) ((x >> 24) & 0xff); this.opcode_type = (byte) ((y >> 0) & 0xff); this.operand_type = (byte) ((y >> 8) & 0xff); this.stack_behavior_pop = (byte) ((y >> 16) & 0xff); this.stack_behavior_push = (byte) ((y >> 24) & 0xff); if (op1 == 0xff) OpCodes.OneByteOpCode [op2] = this; else OpCodes.TwoBytesOpCode [op2] = this; } public override int GetHashCode () { return Value; } public override bool Equals (object obj) { if (!(obj is OpCode)) return false; var opcode = (OpCode) obj; return op1 == opcode.op1 && op2 == opcode.op2; } public bool Equals (OpCode opcode) { return op1 == opcode.op1 && op2 == opcode.op2; } public static bool operator == (OpCode one, OpCode other) { return one.op1 == other.op1 && one.op2 == other.op2; } public static bool operator != (OpCode one, OpCode other) { return one.op1 != other.op1 || one.op2 != other.op2; } public override string ToString () { return Name; } } static class OpCodeNames { internal static readonly string [] names; static OpCodeNames () { var table = new byte [] { 3, 110, 111, 112, 5, 98, 114, 101, 97, 107, 7, 108, 100, 97, 114, 103, 46, 48, 7, 108, 100, 97, 114, 103, 46, 49, 7, 108, 100, 97, 114, 103, 46, 50, 7, 108, 100, 97, 114, 103, 46, 51, 7, 108, 100, 108, 111, 99, 46, 48, 7, 108, 100, 108, 111, 99, 46, 49, 7, 108, 100, 108, 111, 99, 46, 50, 7, 108, 100, 108, 111, 99, 46, 51, 7, 115, 116, 108, 111, 99, 46, 48, 7, 115, 116, 108, 111, 99, 46, 49, 7, 115, 116, 108, 111, 99, 46, 50, 7, 115, 116, 108, 111, 99, 46, 51, 7, 108, 100, 97, 114, 103, 46, 115, 8, 108, 100, 97, 114, 103, 97, 46, 115, 7, 115, 116, 97, 114, 103, 46, 115, 7, 108, 100, 108, 111, 99, 46, 115, 8, 108, 100, 108, 111, 99, 97, 46, 115, 7, 115, 116, 108, 111, 99, 46, 115, 6, 108, 100, 110, 117, 108, 108, 9, 108, 100, 99, 46, 105, 52, 46, 109, 49, 8, 108, 100, 99, 46, 105, 52, 46, 48, 8, 108, 100, 99, 46, 105, 52, 46, 49, 8, 108, 100, 99, 46, 105, 52, 46, 50, 8, 108, 100, 99, 46, 105, 52, 46, 51, 8, 108, 100, 99, 46, 105, 52, 46, 52, 8, 108, 100, 99, 46, 105, 52, 46, 53, 8, 108, 100, 99, 46, 105, 52, 46, 54, 8, 108, 100, 99, 46, 105, 52, 46, 55, 8, 108, 100, 99, 46, 105, 52, 46, 56, 8, 108, 100, 99, 46, 105, 52, 46, 115, 6, 108, 100, 99, 46, 105, 52, 6, 108, 100, 99, 46, 105, 56, 6, 108, 100, 99, 46, 114, 52, 6, 108, 100, 99, 46, 114, 56, 3, 100, 117, 112, 3, 112, 111, 112, 3, 106, 109, 112, 4, 99, 97, 108, 108, 5, 99, 97, 108, 108, 105, 3, 114, 101, 116, 4, 98, 114, 46, 115, 9, 98, 114, 102, 97, 108, 115, 101, 46, 115, 8, 98, 114, 116, 114, 117, 101, 46, 115, 5, 98, 101, 113, 46, 115, 5, 98, 103, 101, 46, 115, 5, 98, 103, 116, 46, 115, 5, 98, 108, 101, 46, 115, 5, 98, 108, 116, 46, 115, 8, 98, 110, 101, 46, 117, 110, 46, 115, 8, 98, 103, 101, 46, 117, 110, 46, 115, 8, 98, 103, 116, 46, 117, 110, 46, 115, 8, 98, 108, 101, 46, 117, 110, 46, 115, 8, 98, 108, 116, 46, 117, 110, 46, 115, 2, 98, 114, 7, 98, 114, 102, 97, 108, 115, 101, 6, 98, 114, 116, 114, 117, 101, 3, 98, 101, 113, 3, 98, 103, 101, 3, 98, 103, 116, 3, 98, 108, 101, 3, 98, 108, 116, 6, 98, 110, 101, 46, 117, 110, 6, 98, 103, 101, 46, 117, 110, 6, 98, 103, 116, 46, 117, 110, 6, 98, 108, 101, 46, 117, 110, 6, 98, 108, 116, 46, 117, 110, 6, 115, 119, 105, 116, 99, 104, 8, 108, 100, 105, 110, 100, 46, 105, 49, 8, 108, 100, 105, 110, 100, 46, 117, 49, 8, 108, 100, 105, 110, 100, 46, 105, 50, 8, 108, 100, 105, 110, 100, 46, 117, 50, 8, 108, 100, 105, 110, 100, 46, 105, 52, 8, 108, 100, 105, 110, 100, 46, 117, 52, 8, 108, 100, 105, 110, 100, 46, 105, 56, 7, 108, 100, 105, 110, 100, 46, 105, 8, 108, 100, 105, 110, 100, 46, 114, 52, 8, 108, 100, 105, 110, 100, 46, 114, 56, 9, 108, 100, 105, 110, 100, 46, 114, 101, 102, 9, 115, 116, 105, 110, 100, 46, 114, 101, 102, 8, 115, 116, 105, 110, 100, 46, 105, 49, 8, 115, 116, 105, 110, 100, 46, 105, 50, 8, 115, 116, 105, 110, 100, 46, 105, 52, 8, 115, 116, 105, 110, 100, 46, 105, 56, 8, 115, 116, 105, 110, 100, 46, 114, 52, 8, 115, 116, 105, 110, 100, 46, 114, 56, 3, 97, 100, 100, 3, 115, 117, 98, 3, 109, 117, 108, 3, 100, 105, 118, 6, 100, 105, 118, 46, 117, 110, 3, 114, 101, 109, 6, 114, 101, 109, 46, 117, 110, 3, 97, 110, 100, 2, 111, 114, 3, 120, 111, 114, 3, 115, 104, 108, 3, 115, 104, 114, 6, 115, 104, 114, 46, 117, 110, 3, 110, 101, 103, 3, 110, 111, 116, 7, 99, 111, 110, 118, 46, 105, 49, 7, 99, 111, 110, 118, 46, 105, 50, 7, 99, 111, 110, 118, 46, 105, 52, 7, 99, 111, 110, 118, 46, 105, 56, 7, 99, 111, 110, 118, 46, 114, 52, 7, 99, 111, 110, 118, 46, 114, 56, 7, 99, 111, 110, 118, 46, 117, 52, 7, 99, 111, 110, 118, 46, 117, 56, 8, 99, 97, 108, 108, 118, 105, 114, 116, 5, 99, 112, 111, 98, 106, 5, 108, 100, 111, 98, 106, 5, 108, 100, 115, 116, 114, 6, 110, 101, 119, 111, 98, 106, 9, 99, 97, 115, 116, 99, 108, 97, 115, 115, 6, 105, 115, 105, 110, 115, 116, 9, 99, 111, 110, 118, 46, 114, 46, 117, 110, 5, 117, 110, 98, 111, 120, 5, 116, 104, 114, 111, 119, 5, 108, 100, 102, 108, 100, 6, 108, 100, 102, 108, 100, 97, 5, 115, 116, 102, 108, 100, 6, 108, 100, 115, 102, 108, 100, 7, 108, 100, 115, 102, 108, 100, 97, 6, 115, 116, 115, 102, 108, 100, 5, 115, 116, 111, 98, 106, 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 49, 46, 117, 110, 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 50, 46, 117, 110, 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 52, 46, 117, 110, 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 56, 46, 117, 110, 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 49, 46, 117, 110, 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 50, 46, 117, 110, 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 52, 46, 117, 110, 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 56, 46, 117, 110, 13, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 46, 117, 110, 13, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 46, 117, 110, 3, 98, 111, 120, 6, 110, 101, 119, 97, 114, 114, 5, 108, 100, 108, 101, 110, 7, 108, 100, 101, 108, 101, 109, 97, 9, 108, 100, 101, 108, 101, 109, 46, 105, 49, 9, 108, 100, 101, 108, 101, 109, 46, 117, 49, 9, 108, 100, 101, 108, 101, 109, 46, 105, 50, 9, 108, 100, 101, 108, 101, 109, 46, 117, 50, 9, 108, 100, 101, 108, 101, 109, 46, 105, 52, 9, 108, 100, 101, 108, 101, 109, 46, 117, 52, 9, 108, 100, 101, 108, 101, 109, 46, 105, 56, 8, 108, 100, 101, 108, 101, 109, 46, 105, 9, 108, 100, 101, 108, 101, 109, 46, 114, 52, 9, 108, 100, 101, 108, 101, 109, 46, 114, 56, 10, 108, 100, 101, 108, 101, 109, 46, 114, 101, 102, 8, 115, 116, 101, 108, 101, 109, 46, 105, 9, 115, 116, 101, 108, 101, 109, 46, 105, 49, 9, 115, 116, 101, 108, 101, 109, 46, 105, 50, 9, 115, 116, 101, 108, 101, 109, 46, 105, 52, 9, 115, 116, 101, 108, 101, 109, 46, 105, 56, 9, 115, 116, 101, 108, 101, 109, 46, 114, 52, 9, 115, 116, 101, 108, 101, 109, 46, 114, 56, 10, 115, 116, 101, 108, 101, 109, 46, 114, 101, 102, 10, 108, 100, 101, 108, 101, 109, 46, 97, 110, 121, 10, 115, 116, 101, 108, 101, 109, 46, 97, 110, 121, 9, 117, 110, 98, 111, 120, 46, 97, 110, 121, 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 49, 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 49, 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 50, 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 50, 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 52, 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 52, 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 56, 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 56, 9, 114, 101, 102, 97, 110, 121, 118, 97, 108, 8, 99, 107, 102, 105, 110, 105, 116, 101, 8, 109, 107, 114, 101, 102, 97, 110, 121, 7, 108, 100, 116, 111, 107, 101, 110, 7, 99, 111, 110, 118, 46, 117, 50, 7, 99, 111, 110, 118, 46, 117, 49, 6, 99, 111, 110, 118, 46, 105, 10, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 10, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 7, 97, 100, 100, 46, 111, 118, 102, 10, 97, 100, 100, 46, 111, 118, 102, 46, 117, 110, 7, 109, 117, 108, 46, 111, 118, 102, 10, 109, 117, 108, 46, 111, 118, 102, 46, 117, 110, 7, 115, 117, 98, 46, 111, 118, 102, 10, 115, 117, 98, 46, 111, 118, 102, 46, 117, 110, 10, 101, 110, 100, 102, 105, 110, 97, 108, 108, 121, 5, 108, 101, 97, 118, 101, 7, 108, 101, 97, 118, 101, 46, 115, 7, 115, 116, 105, 110, 100, 46, 105, 6, 99, 111, 110, 118, 46, 117, 7, 97, 114, 103, 108, 105, 115, 116, 3, 99, 101, 113, 3, 99, 103, 116, 6, 99, 103, 116, 46, 117, 110, 3, 99, 108, 116, 6, 99, 108, 116, 46, 117, 110, 5, 108, 100, 102, 116, 110, 9, 108, 100, 118, 105, 114, 116, 102, 116, 110, 5, 108, 100, 97, 114, 103, 6, 108, 100, 97, 114, 103, 97, 5, 115, 116, 97, 114, 103, 5, 108, 100, 108, 111, 99, 6, 108, 100, 108, 111, 99, 97, 5, 115, 116, 108, 111, 99, 8, 108, 111, 99, 97, 108, 108, 111, 99, 9, 101, 110, 100, 102, 105, 108, 116, 101, 114, 10, 117, 110, 97, 108, 105, 103, 110, 101, 100, 46, 9, 118, 111, 108, 97, 116, 105, 108, 101, 46, 5, 116, 97, 105, 108, 46, 7, 105, 110, 105, 116, 111, 98, 106, 12, 99, 111, 110, 115, 116, 114, 97, 105, 110, 101, 100, 46, 5, 99, 112, 98, 108, 107, 7, 105, 110, 105, 116, 98, 108, 107, 3, 110, 111, 46, 7, 114, 101, 116, 104, 114, 111, 119, 6, 115, 105, 122, 101, 111, 102, 10, 114, 101, 102, 97, 110, 121, 116, 121, 112, 101, 9, 114, 101, 97, 100, 111, 110, 108, 121, 46, }; names = new string [219]; for (int i = 0, p = 0; i < names.Length; i++) { var buffer = new char [table [p++]]; for (int j = 0; j < buffer.Length; j++) buffer [j] = (char) table [p++]; names [i] = new string (buffer); } } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/OpCodes.cs ================================================ // // OpCodes.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil.Cil { public static class OpCodes { internal static readonly OpCode [] OneByteOpCode = new OpCode [0xe0 + 1]; internal static readonly OpCode [] TwoBytesOpCode = new OpCode [0x1e + 1]; public static readonly OpCode Nop = new OpCode ( 0xff << 0 | 0x00 << 8 | (byte) Code.Nop << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Break = new OpCode ( 0xff << 0 | 0x01 << 8 | (byte) Code.Break << 16 | (byte) FlowControl.Break << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldarg_0 = new OpCode ( 0xff << 0 | 0x02 << 8 | (byte) Code.Ldarg_0 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldarg_1 = new OpCode ( 0xff << 0 | 0x03 << 8 | (byte) Code.Ldarg_1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldarg_2 = new OpCode ( 0xff << 0 | 0x04 << 8 | (byte) Code.Ldarg_2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldarg_3 = new OpCode ( 0xff << 0 | 0x05 << 8 | (byte) Code.Ldarg_3 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldloc_0 = new OpCode ( 0xff << 0 | 0x06 << 8 | (byte) Code.Ldloc_0 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldloc_1 = new OpCode ( 0xff << 0 | 0x07 << 8 | (byte) Code.Ldloc_1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldloc_2 = new OpCode ( 0xff << 0 | 0x08 << 8 | (byte) Code.Ldloc_2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldloc_3 = new OpCode ( 0xff << 0 | 0x09 << 8 | (byte) Code.Ldloc_3 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Stloc_0 = new OpCode ( 0xff << 0 | 0x0a << 8 | (byte) Code.Stloc_0 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stloc_1 = new OpCode ( 0xff << 0 | 0x0b << 8 | (byte) Code.Stloc_1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stloc_2 = new OpCode ( 0xff << 0 | 0x0c << 8 | (byte) Code.Stloc_2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stloc_3 = new OpCode ( 0xff << 0 | 0x0d << 8 | (byte) Code.Stloc_3 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldarg_S = new OpCode ( 0xff << 0 | 0x0e << 8 | (byte) Code.Ldarg_S << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineArg << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldarga_S = new OpCode ( 0xff << 0 | 0x0f << 8 | (byte) Code.Ldarga_S << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineArg << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Starg_S = new OpCode ( 0xff << 0 | 0x10 << 8 | (byte) Code.Starg_S << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineArg << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldloc_S = new OpCode ( 0xff << 0 | 0x11 << 8 | (byte) Code.Ldloc_S << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineVar << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldloca_S = new OpCode ( 0xff << 0 | 0x12 << 8 | (byte) Code.Ldloca_S << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineVar << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Stloc_S = new OpCode ( 0xff << 0 | 0x13 << 8 | (byte) Code.Stloc_S << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineVar << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldnull = new OpCode ( 0xff << 0 | 0x14 << 8 | (byte) Code.Ldnull << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushref << 24); public static readonly OpCode Ldc_I4_M1 = new OpCode ( 0xff << 0 | 0x15 << 8 | (byte) Code.Ldc_I4_M1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_0 = new OpCode ( 0xff << 0 | 0x16 << 8 | (byte) Code.Ldc_I4_0 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_1 = new OpCode ( 0xff << 0 | 0x17 << 8 | (byte) Code.Ldc_I4_1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_2 = new OpCode ( 0xff << 0 | 0x18 << 8 | (byte) Code.Ldc_I4_2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_3 = new OpCode ( 0xff << 0 | 0x19 << 8 | (byte) Code.Ldc_I4_3 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_4 = new OpCode ( 0xff << 0 | 0x1a << 8 | (byte) Code.Ldc_I4_4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_5 = new OpCode ( 0xff << 0 | 0x1b << 8 | (byte) Code.Ldc_I4_5 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_6 = new OpCode ( 0xff << 0 | 0x1c << 8 | (byte) Code.Ldc_I4_6 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_7 = new OpCode ( 0xff << 0 | 0x1d << 8 | (byte) Code.Ldc_I4_7 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_8 = new OpCode ( 0xff << 0 | 0x1e << 8 | (byte) Code.Ldc_I4_8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4_S = new OpCode ( 0xff << 0 | 0x1f << 8 | (byte) Code.Ldc_I4_S << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineI << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I4 = new OpCode ( 0xff << 0 | 0x20 << 8 | (byte) Code.Ldc_I4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineI << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldc_I8 = new OpCode ( 0xff << 0 | 0x21 << 8 | (byte) Code.Ldc_I8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineI8 << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi8 << 24); public static readonly OpCode Ldc_R4 = new OpCode ( 0xff << 0 | 0x22 << 8 | (byte) Code.Ldc_R4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.ShortInlineR << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushr4 << 24); public static readonly OpCode Ldc_R8 = new OpCode ( 0xff << 0 | 0x23 << 8 | (byte) Code.Ldc_R8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineR << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushr8 << 24); public static readonly OpCode Dup = new OpCode ( 0xff << 0 | 0x25 << 8 | (byte) Code.Dup << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push1_push1 << 24); public static readonly OpCode Pop = new OpCode ( 0xff << 0 | 0x26 << 8 | (byte) Code.Pop << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Jmp = new OpCode ( 0xff << 0 | 0x27 << 8 | (byte) Code.Jmp << 16 | (byte) FlowControl.Call << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Call = new OpCode ( 0xff << 0 | 0x28 << 8 | (byte) Code.Call << 16 | (byte) FlowControl.Call << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Varpush << 24); public static readonly OpCode Calli = new OpCode ( 0xff << 0 | 0x29 << 8 | (byte) Code.Calli << 16 | (byte) FlowControl.Call << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineSig << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Varpush << 24); public static readonly OpCode Ret = new OpCode ( 0xff << 0 | 0x2a << 8 | (byte) Code.Ret << 16 | (byte) FlowControl.Return << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Br_S = new OpCode ( 0xff << 0 | 0x2b << 8 | (byte) Code.Br_S << 16 | (byte) FlowControl.Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Brfalse_S = new OpCode ( 0xff << 0 | 0x2c << 8 | (byte) Code.Brfalse_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Brtrue_S = new OpCode ( 0xff << 0 | 0x2d << 8 | (byte) Code.Brtrue_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Beq_S = new OpCode ( 0xff << 0 | 0x2e << 8 | (byte) Code.Beq_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bge_S = new OpCode ( 0xff << 0 | 0x2f << 8 | (byte) Code.Bge_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bgt_S = new OpCode ( 0xff << 0 | 0x30 << 8 | (byte) Code.Bgt_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ble_S = new OpCode ( 0xff << 0 | 0x31 << 8 | (byte) Code.Ble_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Blt_S = new OpCode ( 0xff << 0 | 0x32 << 8 | (byte) Code.Blt_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bne_Un_S = new OpCode ( 0xff << 0 | 0x33 << 8 | (byte) Code.Bne_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bge_Un_S = new OpCode ( 0xff << 0 | 0x34 << 8 | (byte) Code.Bge_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bgt_Un_S = new OpCode ( 0xff << 0 | 0x35 << 8 | (byte) Code.Bgt_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ble_Un_S = new OpCode ( 0xff << 0 | 0x36 << 8 | (byte) Code.Ble_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Blt_Un_S = new OpCode ( 0xff << 0 | 0x37 << 8 | (byte) Code.Blt_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Br = new OpCode ( 0xff << 0 | 0x38 << 8 | (byte) Code.Br << 16 | (byte) FlowControl.Branch << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Brfalse = new OpCode ( 0xff << 0 | 0x39 << 8 | (byte) Code.Brfalse << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Brtrue = new OpCode ( 0xff << 0 | 0x3a << 8 | (byte) Code.Brtrue << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Beq = new OpCode ( 0xff << 0 | 0x3b << 8 | (byte) Code.Beq << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bge = new OpCode ( 0xff << 0 | 0x3c << 8 | (byte) Code.Bge << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bgt = new OpCode ( 0xff << 0 | 0x3d << 8 | (byte) Code.Bgt << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ble = new OpCode ( 0xff << 0 | 0x3e << 8 | (byte) Code.Ble << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Blt = new OpCode ( 0xff << 0 | 0x3f << 8 | (byte) Code.Blt << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bne_Un = new OpCode ( 0xff << 0 | 0x40 << 8 | (byte) Code.Bne_Un << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bge_Un = new OpCode ( 0xff << 0 | 0x41 << 8 | (byte) Code.Bge_Un << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Bgt_Un = new OpCode ( 0xff << 0 | 0x42 << 8 | (byte) Code.Bgt_Un << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ble_Un = new OpCode ( 0xff << 0 | 0x43 << 8 | (byte) Code.Ble_Un << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Blt_Un = new OpCode ( 0xff << 0 | 0x44 << 8 | (byte) Code.Blt_Un << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Switch = new OpCode ( 0xff << 0 | 0x45 << 8 | (byte) Code.Switch << 16 | (byte) FlowControl.Cond_Branch << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineSwitch << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldind_I1 = new OpCode ( 0xff << 0 | 0x46 << 8 | (byte) Code.Ldind_I1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldind_U1 = new OpCode ( 0xff << 0 | 0x47 << 8 | (byte) Code.Ldind_U1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldind_I2 = new OpCode ( 0xff << 0 | 0x48 << 8 | (byte) Code.Ldind_I2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldind_U2 = new OpCode ( 0xff << 0 | 0x49 << 8 | (byte) Code.Ldind_U2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldind_I4 = new OpCode ( 0xff << 0 | 0x4a << 8 | (byte) Code.Ldind_I4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldind_U4 = new OpCode ( 0xff << 0 | 0x4b << 8 | (byte) Code.Ldind_U4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldind_I8 = new OpCode ( 0xff << 0 | 0x4c << 8 | (byte) Code.Ldind_I8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi8 << 24); public static readonly OpCode Ldind_I = new OpCode ( 0xff << 0 | 0x4d << 8 | (byte) Code.Ldind_I << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldind_R4 = new OpCode ( 0xff << 0 | 0x4e << 8 | (byte) Code.Ldind_R4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushr4 << 24); public static readonly OpCode Ldind_R8 = new OpCode ( 0xff << 0 | 0x4f << 8 | (byte) Code.Ldind_R8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushr8 << 24); public static readonly OpCode Ldind_Ref = new OpCode ( 0xff << 0 | 0x50 << 8 | (byte) Code.Ldind_Ref << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushref << 24); public static readonly OpCode Stind_Ref = new OpCode ( 0xff << 0 | 0x51 << 8 | (byte) Code.Stind_Ref << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stind_I1 = new OpCode ( 0xff << 0 | 0x52 << 8 | (byte) Code.Stind_I1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stind_I2 = new OpCode ( 0xff << 0 | 0x53 << 8 | (byte) Code.Stind_I2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stind_I4 = new OpCode ( 0xff << 0 | 0x54 << 8 | (byte) Code.Stind_I4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stind_I8 = new OpCode ( 0xff << 0 | 0x55 << 8 | (byte) Code.Stind_I8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi8 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stind_R4 = new OpCode ( 0xff << 0 | 0x56 << 8 | (byte) Code.Stind_R4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popr4 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stind_R8 = new OpCode ( 0xff << 0 | 0x57 << 8 | (byte) Code.Stind_R8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popr8 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Add = new OpCode ( 0xff << 0 | 0x58 << 8 | (byte) Code.Add << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Sub = new OpCode ( 0xff << 0 | 0x59 << 8 | (byte) Code.Sub << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Mul = new OpCode ( 0xff << 0 | 0x5a << 8 | (byte) Code.Mul << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Div = new OpCode ( 0xff << 0 | 0x5b << 8 | (byte) Code.Div << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Div_Un = new OpCode ( 0xff << 0 | 0x5c << 8 | (byte) Code.Div_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Rem = new OpCode ( 0xff << 0 | 0x5d << 8 | (byte) Code.Rem << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Rem_Un = new OpCode ( 0xff << 0 | 0x5e << 8 | (byte) Code.Rem_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode And = new OpCode ( 0xff << 0 | 0x5f << 8 | (byte) Code.And << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Or = new OpCode ( 0xff << 0 | 0x60 << 8 | (byte) Code.Or << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Xor = new OpCode ( 0xff << 0 | 0x61 << 8 | (byte) Code.Xor << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Shl = new OpCode ( 0xff << 0 | 0x62 << 8 | (byte) Code.Shl << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Shr = new OpCode ( 0xff << 0 | 0x63 << 8 | (byte) Code.Shr << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Shr_Un = new OpCode ( 0xff << 0 | 0x64 << 8 | (byte) Code.Shr_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Neg = new OpCode ( 0xff << 0 | 0x65 << 8 | (byte) Code.Neg << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Not = new OpCode ( 0xff << 0 | 0x66 << 8 | (byte) Code.Not << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Conv_I1 = new OpCode ( 0xff << 0 | 0x67 << 8 | (byte) Code.Conv_I1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_I2 = new OpCode ( 0xff << 0 | 0x68 << 8 | (byte) Code.Conv_I2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_I4 = new OpCode ( 0xff << 0 | 0x69 << 8 | (byte) Code.Conv_I4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_I8 = new OpCode ( 0xff << 0 | 0x6a << 8 | (byte) Code.Conv_I8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24); public static readonly OpCode Conv_R4 = new OpCode ( 0xff << 0 | 0x6b << 8 | (byte) Code.Conv_R4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushr4 << 24); public static readonly OpCode Conv_R8 = new OpCode ( 0xff << 0 | 0x6c << 8 | (byte) Code.Conv_R8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushr8 << 24); public static readonly OpCode Conv_U4 = new OpCode ( 0xff << 0 | 0x6d << 8 | (byte) Code.Conv_U4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_U8 = new OpCode ( 0xff << 0 | 0x6e << 8 | (byte) Code.Conv_U8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24); public static readonly OpCode Callvirt = new OpCode ( 0xff << 0 | 0x6f << 8 | (byte) Code.Callvirt << 16 | (byte) FlowControl.Call << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Varpush << 24); public static readonly OpCode Cpobj = new OpCode ( 0xff << 0 | 0x70 << 8 | (byte) Code.Cpobj << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldobj = new OpCode ( 0xff << 0 | 0x71 << 8 | (byte) Code.Ldobj << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldstr = new OpCode ( 0xff << 0 | 0x72 << 8 | (byte) Code.Ldstr << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineString << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushref << 24); public static readonly OpCode Newobj = new OpCode ( 0xff << 0 | 0x73 << 8 | (byte) Code.Newobj << 16 | (byte) FlowControl.Call << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Pushref << 24); public static readonly OpCode Castclass = new OpCode ( 0xff << 0 | 0x74 << 8 | (byte) Code.Castclass << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushref << 24); public static readonly OpCode Isinst = new OpCode ( 0xff << 0 | 0x75 << 8 | (byte) Code.Isinst << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_R_Un = new OpCode ( 0xff << 0 | 0x76 << 8 | (byte) Code.Conv_R_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushr8 << 24); public static readonly OpCode Unbox = new OpCode ( 0xff << 0 | 0x79 << 8 | (byte) Code.Unbox << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Throw = new OpCode ( 0xff << 0 | 0x7a << 8 | (byte) Code.Throw << 16 | (byte) FlowControl.Throw << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldfld = new OpCode ( 0xff << 0 | 0x7b << 8 | (byte) Code.Ldfld << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldflda = new OpCode ( 0xff << 0 | 0x7c << 8 | (byte) Code.Ldflda << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Stfld = new OpCode ( 0xff << 0 | 0x7d << 8 | (byte) Code.Stfld << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Popref_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldsfld = new OpCode ( 0xff << 0 | 0x7e << 8 | (byte) Code.Ldsfld << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldsflda = new OpCode ( 0xff << 0 | 0x7f << 8 | (byte) Code.Ldsflda << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Stsfld = new OpCode ( 0xff << 0 | 0x80 << 8 | (byte) Code.Stsfld << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stobj = new OpCode ( 0xff << 0 | 0x81 << 8 | (byte) Code.Stobj << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Conv_Ovf_I1_Un = new OpCode ( 0xff << 0 | 0x82 << 8 | (byte) Code.Conv_Ovf_I1_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_I2_Un = new OpCode ( 0xff << 0 | 0x83 << 8 | (byte) Code.Conv_Ovf_I2_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_I4_Un = new OpCode ( 0xff << 0 | 0x84 << 8 | (byte) Code.Conv_Ovf_I4_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_I8_Un = new OpCode ( 0xff << 0 | 0x85 << 8 | (byte) Code.Conv_Ovf_I8_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24); public static readonly OpCode Conv_Ovf_U1_Un = new OpCode ( 0xff << 0 | 0x86 << 8 | (byte) Code.Conv_Ovf_U1_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_U2_Un = new OpCode ( 0xff << 0 | 0x87 << 8 | (byte) Code.Conv_Ovf_U2_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_U4_Un = new OpCode ( 0xff << 0 | 0x88 << 8 | (byte) Code.Conv_Ovf_U4_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_U8_Un = new OpCode ( 0xff << 0 | 0x89 << 8 | (byte) Code.Conv_Ovf_U8_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24); public static readonly OpCode Conv_Ovf_I_Un = new OpCode ( 0xff << 0 | 0x8a << 8 | (byte) Code.Conv_Ovf_I_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_U_Un = new OpCode ( 0xff << 0 | 0x8b << 8 | (byte) Code.Conv_Ovf_U_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Box = new OpCode ( 0xff << 0 | 0x8c << 8 | (byte) Code.Box << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushref << 24); public static readonly OpCode Newarr = new OpCode ( 0xff << 0 | 0x8d << 8 | (byte) Code.Newarr << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushref << 24); public static readonly OpCode Ldlen = new OpCode ( 0xff << 0 | 0x8e << 8 | (byte) Code.Ldlen << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldelema = new OpCode ( 0xff << 0 | 0x8f << 8 | (byte) Code.Ldelema << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldelem_I1 = new OpCode ( 0xff << 0 | 0x90 << 8 | (byte) Code.Ldelem_I1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldelem_U1 = new OpCode ( 0xff << 0 | 0x91 << 8 | (byte) Code.Ldelem_U1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldelem_I2 = new OpCode ( 0xff << 0 | 0x92 << 8 | (byte) Code.Ldelem_I2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldelem_U2 = new OpCode ( 0xff << 0 | 0x93 << 8 | (byte) Code.Ldelem_U2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldelem_I4 = new OpCode ( 0xff << 0 | 0x94 << 8 | (byte) Code.Ldelem_I4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldelem_U4 = new OpCode ( 0xff << 0 | 0x95 << 8 | (byte) Code.Ldelem_U4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldelem_I8 = new OpCode ( 0xff << 0 | 0x96 << 8 | (byte) Code.Ldelem_I8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi8 << 24); public static readonly OpCode Ldelem_I = new OpCode ( 0xff << 0 | 0x97 << 8 | (byte) Code.Ldelem_I << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldelem_R4 = new OpCode ( 0xff << 0 | 0x98 << 8 | (byte) Code.Ldelem_R4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushr4 << 24); public static readonly OpCode Ldelem_R8 = new OpCode ( 0xff << 0 | 0x99 << 8 | (byte) Code.Ldelem_R8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushr8 << 24); public static readonly OpCode Ldelem_Ref = new OpCode ( 0xff << 0 | 0x9a << 8 | (byte) Code.Ldelem_Ref << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushref << 24); public static readonly OpCode Stelem_I = new OpCode ( 0xff << 0 | 0x9b << 8 | (byte) Code.Stelem_I << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stelem_I1 = new OpCode ( 0xff << 0 | 0x9c << 8 | (byte) Code.Stelem_I1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stelem_I2 = new OpCode ( 0xff << 0 | 0x9d << 8 | (byte) Code.Stelem_I2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stelem_I4 = new OpCode ( 0xff << 0 | 0x9e << 8 | (byte) Code.Stelem_I4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stelem_I8 = new OpCode ( 0xff << 0 | 0x9f << 8 | (byte) Code.Stelem_I8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi8 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stelem_R4 = new OpCode ( 0xff << 0 | 0xa0 << 8 | (byte) Code.Stelem_R4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popr4 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stelem_R8 = new OpCode ( 0xff << 0 | 0xa1 << 8 | (byte) Code.Stelem_R8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popr8 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stelem_Ref = new OpCode ( 0xff << 0 | 0xa2 << 8 | (byte) Code.Stelem_Ref << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popref << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldelem_Any = new OpCode ( 0xff << 0 | 0xa3 << 8 | (byte) Code.Ldelem_Any << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Stelem_Any = new OpCode ( 0xff << 0 | 0xa4 << 8 | (byte) Code.Stelem_Any << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref_popi_popref << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Unbox_Any = new OpCode ( 0xff << 0 | 0xa5 << 8 | (byte) Code.Unbox_Any << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Conv_Ovf_I1 = new OpCode ( 0xff << 0 | 0xb3 << 8 | (byte) Code.Conv_Ovf_I1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_U1 = new OpCode ( 0xff << 0 | 0xb4 << 8 | (byte) Code.Conv_Ovf_U1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_I2 = new OpCode ( 0xff << 0 | 0xb5 << 8 | (byte) Code.Conv_Ovf_I2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_U2 = new OpCode ( 0xff << 0 | 0xb6 << 8 | (byte) Code.Conv_Ovf_U2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_I4 = new OpCode ( 0xff << 0 | 0xb7 << 8 | (byte) Code.Conv_Ovf_I4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_U4 = new OpCode ( 0xff << 0 | 0xb8 << 8 | (byte) Code.Conv_Ovf_U4 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_I8 = new OpCode ( 0xff << 0 | 0xb9 << 8 | (byte) Code.Conv_Ovf_I8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24); public static readonly OpCode Conv_Ovf_U8 = new OpCode ( 0xff << 0 | 0xba << 8 | (byte) Code.Conv_Ovf_U8 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24); public static readonly OpCode Refanyval = new OpCode ( 0xff << 0 | 0xc2 << 8 | (byte) Code.Refanyval << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ckfinite = new OpCode ( 0xff << 0 | 0xc3 << 8 | (byte) Code.Ckfinite << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushr8 << 24); public static readonly OpCode Mkrefany = new OpCode ( 0xff << 0 | 0xc6 << 8 | (byte) Code.Mkrefany << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldtoken = new OpCode ( 0xff << 0 | 0xd0 << 8 | (byte) Code.Ldtoken << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineTok << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_U2 = new OpCode ( 0xff << 0 | 0xd1 << 8 | (byte) Code.Conv_U2 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_U1 = new OpCode ( 0xff << 0 | 0xd2 << 8 | (byte) Code.Conv_U1 << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_I = new OpCode ( 0xff << 0 | 0xd3 << 8 | (byte) Code.Conv_I << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_I = new OpCode ( 0xff << 0 | 0xd4 << 8 | (byte) Code.Conv_Ovf_I << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Conv_Ovf_U = new OpCode ( 0xff << 0 | 0xd5 << 8 | (byte) Code.Conv_Ovf_U << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Add_Ovf = new OpCode ( 0xff << 0 | 0xd6 << 8 | (byte) Code.Add_Ovf << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Add_Ovf_Un = new OpCode ( 0xff << 0 | 0xd7 << 8 | (byte) Code.Add_Ovf_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Mul_Ovf = new OpCode ( 0xff << 0 | 0xd8 << 8 | (byte) Code.Mul_Ovf << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Mul_Ovf_Un = new OpCode ( 0xff << 0 | 0xd9 << 8 | (byte) Code.Mul_Ovf_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Sub_Ovf = new OpCode ( 0xff << 0 | 0xda << 8 | (byte) Code.Sub_Ovf << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Sub_Ovf_Un = new OpCode ( 0xff << 0 | 0xdb << 8 | (byte) Code.Sub_Ovf_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Endfinally = new OpCode ( 0xff << 0 | 0xdc << 8 | (byte) Code.Endfinally << 16 | (byte) FlowControl.Return << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Leave = new OpCode ( 0xff << 0 | 0xdd << 8 | (byte) Code.Leave << 16 | (byte) FlowControl.Branch << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.PopAll << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Leave_S = new OpCode ( 0xff << 0 | 0xde << 8 | (byte) Code.Leave_S << 16 | (byte) FlowControl.Branch << 24, (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.PopAll << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Stind_I = new OpCode ( 0xff << 0 | 0xdf << 8 | (byte) Code.Stind_I << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Conv_U = new OpCode ( 0xff << 0 | 0xe0 << 8 | (byte) Code.Conv_U << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Arglist = new OpCode ( 0xfe << 0 | 0x00 << 8 | (byte) Code.Arglist << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ceq = new OpCode ( 0xfe << 0 | 0x01 << 8 | (byte) Code.Ceq << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Cgt = new OpCode ( 0xfe << 0 | 0x02 << 8 | (byte) Code.Cgt << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Cgt_Un = new OpCode ( 0xfe << 0 | 0x03 << 8 | (byte) Code.Cgt_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Clt = new OpCode ( 0xfe << 0 | 0x04 << 8 | (byte) Code.Clt << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Clt_Un = new OpCode ( 0xfe << 0 | 0x05 << 8 | (byte) Code.Clt_Un << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldftn = new OpCode ( 0xfe << 0 | 0x06 << 8 | (byte) Code.Ldftn << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldvirtftn = new OpCode ( 0xfe << 0 | 0x07 << 8 | (byte) Code.Ldvirtftn << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Ldarg = new OpCode ( 0xfe << 0 | 0x09 << 8 | (byte) Code.Ldarg << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineArg << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldarga = new OpCode ( 0xfe << 0 | 0x0a << 8 | (byte) Code.Ldarga << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineArg << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Starg = new OpCode ( 0xfe << 0 | 0x0b << 8 | (byte) Code.Starg << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineArg << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Ldloc = new OpCode ( 0xfe << 0 | 0x0c << 8 | (byte) Code.Ldloc << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineVar << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); public static readonly OpCode Ldloca = new OpCode ( 0xfe << 0 | 0x0d << 8 | (byte) Code.Ldloca << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineVar << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Stloc = new OpCode ( 0xfe << 0 | 0x0e << 8 | (byte) Code.Stloc << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineVar << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Localloc = new OpCode ( 0xfe << 0 | 0x0f << 8 | (byte) Code.Localloc << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Endfilter = new OpCode ( 0xfe << 0 | 0x11 << 8 | (byte) Code.Endfilter << 16 | (byte) FlowControl.Return << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Unaligned = new OpCode ( 0xfe << 0 | 0x12 << 8 | (byte) Code.Unaligned << 16 | (byte) FlowControl.Meta << 24, (byte) OpCodeType.Prefix << 0 | (byte) OperandType.ShortInlineI << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Volatile = new OpCode ( 0xfe << 0 | 0x13 << 8 | (byte) Code.Volatile << 16 | (byte) FlowControl.Meta << 24, (byte) OpCodeType.Prefix << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Tail = new OpCode ( 0xfe << 0 | 0x14 << 8 | (byte) Code.Tail << 16 | (byte) FlowControl.Meta << 24, (byte) OpCodeType.Prefix << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Initobj = new OpCode ( 0xfe << 0 | 0x15 << 8 | (byte) Code.Initobj << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Constrained = new OpCode ( 0xfe << 0 | 0x16 << 8 | (byte) Code.Constrained << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Prefix << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Cpblk = new OpCode ( 0xfe << 0 | 0x17 << 8 | (byte) Code.Cpblk << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Initblk = new OpCode ( 0xfe << 0 | 0x18 << 8 | (byte) Code.Initblk << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode No = new OpCode ( 0xfe << 0 | 0x19 << 8 | (byte) Code.No << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Prefix << 0 | (byte) OperandType.ShortInlineI << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Rethrow = new OpCode ( 0xfe << 0 | 0x1a << 8 | (byte) Code.Rethrow << 16 | (byte) FlowControl.Throw << 24, (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); public static readonly OpCode Sizeof = new OpCode ( 0xfe << 0 | 0x1c << 8 | (byte) Code.Sizeof << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Refanytype = new OpCode ( 0xfe << 0 | 0x1d << 8 | (byte) Code.Refanytype << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); public static readonly OpCode Readonly = new OpCode ( 0xfe << 0 | 0x1e << 8 | (byte) Code.Readonly << 16 | (byte) FlowControl.Next << 24, (byte) OpCodeType.Prefix << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/SequencePoint.cs ================================================ // // SequencePoint.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil.Cil { public sealed class SequencePoint { Document document; int start_line; int start_column; int end_line; int end_column; public int StartLine { get { return start_line; } set { start_line = value; } } public int StartColumn { get { return start_column; } set { start_column = value; } } public int EndLine { get { return end_line; } set { end_line = value; } } public int EndColumn { get { return end_column; } set { end_column = value; } } public Document Document { get { return document; } set { document = value; } } public SequencePoint (Document document) { this.document = document; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/Symbols.cs ================================================ // // Symbols.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.IO; using System.Runtime.InteropServices; using SR = System.Reflection; using Mono.Collections.Generic; namespace Mono.Cecil.Cil { [StructLayout (LayoutKind.Sequential)] public struct ImageDebugDirectory { public int Characteristics; public int TimeDateStamp; public short MajorVersion; public short MinorVersion; public int Type; public int SizeOfData; public int AddressOfRawData; public int PointerToRawData; } public sealed class Scope : IVariableDefinitionProvider { Instruction start; Instruction end; Collection scopes; Collection variables; public Instruction Start { get { return start; } set { start = value; } } public Instruction End { get { return end; } set { end = value; } } public bool HasScopes { get { return !Mixin.IsNullOrEmpty (scopes); } } public Collection Scopes { get { if (scopes == null) scopes = new Collection (); return scopes; } } public bool HasVariables { get { return !Mixin.IsNullOrEmpty (variables); } } public Collection Variables { get { if (variables == null) variables = new Collection (); return variables; } } } public struct InstructionSymbol { public readonly int Offset; public readonly SequencePoint SequencePoint; public InstructionSymbol (int offset, SequencePoint sequencePoint) { this.Offset = offset; this.SequencePoint = sequencePoint; } } public sealed class MethodSymbols { internal int code_size; internal string method_name; internal MetadataToken method_token; internal MetadataToken local_var_token; internal Collection variables; public Collection instructions; public bool HasVariables { get { return !Mixin.IsNullOrEmpty (variables); } } public Collection Variables { get { if (variables == null) variables = new Collection (); return variables; } } public Collection Instructions { get { if (instructions == null) instructions = new Collection (); return instructions; } } public int CodeSize { get { return code_size; } } public string MethodName { get { return method_name; } } public MetadataToken MethodToken { get { return method_token; } } public MetadataToken LocalVarToken { get { return local_var_token; } } internal MethodSymbols (string methodName) { this.method_name = methodName; } public MethodSymbols (MetadataToken methodToken) { this.method_token = methodToken; } } public delegate Instruction InstructionMapper (int offset); public interface ISymbolReader : IDisposable { bool ProcessDebugHeader (ImageDebugDirectory directory, byte [] header); void Read (MethodBody body, InstructionMapper mapper); void Read (MethodSymbols symbols); } public interface ISymbolReaderProvider { ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName); ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream); } static class SymbolProvider { static readonly string symbol_kind = Type.GetType ("Mono.Runtime") != null ? "Mdb" : "Pdb"; static SR.AssemblyName GetPlatformSymbolAssemblyName () { var cecil_name = typeof (SymbolProvider).Assembly.GetName (); var name = new SR.AssemblyName { Name = "Mono.Cecil." + symbol_kind, Version = cecil_name.Version, }; name.SetPublicKeyToken (cecil_name.GetPublicKeyToken ()); return name; } static Type GetPlatformType (string fullname) { var type = Type.GetType (fullname); if (type != null) return type; var assembly_name = GetPlatformSymbolAssemblyName (); type = Type.GetType (fullname + ", " + assembly_name.FullName); if (type != null) return type; try { var assembly = SR.Assembly.Load (assembly_name); if (assembly != null) return assembly.GetType (fullname); } catch (FileNotFoundException) { } return null; } static ISymbolReaderProvider reader_provider; public static ISymbolReaderProvider GetPlatformReaderProvider () { if (reader_provider != null) return reader_provider; var type = GetPlatformType (GetProviderTypeName ("ReaderProvider")); if (type == null) return null; return reader_provider = (ISymbolReaderProvider) Activator.CreateInstance (type); } static string GetProviderTypeName (string name) { return "Mono.Cecil." + symbol_kind + "." + symbol_kind + name; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/VariableDefinition.cs ================================================ // // VariableDefinition.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil.Cil { public sealed class VariableDefinition : VariableReference { public bool IsPinned { get { return variable_type.IsPinned; } } public VariableDefinition (TypeReference variableType) : base (variableType) { } public VariableDefinition (string name, TypeReference variableType) : base (name, variableType) { } public override VariableDefinition Resolve () { return this; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Cil/VariableReference.cs ================================================ // // VariableReference.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil.Cil { public abstract class VariableReference { string name; internal int index = -1; protected TypeReference variable_type; public string Name { get { return name; } set { name = value; } } public TypeReference VariableType { get { return variable_type; } set { variable_type = value; } } public int Index { get { return index; } } internal VariableReference (TypeReference variable_type) : this (string.Empty, variable_type) { } internal VariableReference (string name, TypeReference variable_type) { this.name = name; this.variable_type = variable_type; } public abstract VariableDefinition Resolve (); public override string ToString () { if (!string.IsNullOrEmpty (name)) return name; if (index >= 0) return "V_" + index; return string.Empty; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/BlobHeap.cs ================================================ // // BlobHeap.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.PE; namespace Mono.Cecil.Metadata { sealed class BlobHeap : Heap { public BlobHeap(Section section, uint start, uint size) : base(section, start, size) { } public byte[] Read(uint index) { if (index == 0 || index > Size - 1) return Empty.Array; var data = Section.Data; int position = (int)(index + Offset); int length = (int)Mixin.ReadCompressedUInt32(data, ref position); var buffer = new byte[length]; Buffer.BlockCopy(data, position, buffer, 0, length); return buffer; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/Buffers.cs ================================================ // // TableHeapBuffer.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using System.Text; using Mono.Cecil.PE; using RVA = System.UInt32; ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/CodedIndex.cs ================================================ // // CodedIndex.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil.Metadata { enum CodedIndex { TypeDefOrRef, HasConstant, HasCustomAttribute, HasFieldMarshal, HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef, MemberForwarded, Implementation, CustomAttributeType, ResolutionScope, TypeOrMethodDef } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/ElementType.cs ================================================ // // ElementType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil.Metadata { enum ElementType : byte { None = 0x00, Void = 0x01, Boolean = 0x02, Char = 0x03, I1 = 0x04, U1 = 0x05, I2 = 0x06, U2 = 0x07, I4 = 0x08, U4 = 0x09, I8 = 0x0a, U8 = 0x0b, R4 = 0x0c, R8 = 0x0d, String = 0x0e, Ptr = 0x0f, // Followed by token ByRef = 0x10, // Followed by token ValueType = 0x11, // Followed by token Class = 0x12, // Followed by token Var = 0x13, // Followed by generic parameter number Array = 0x14, // GenericInst = 0x15, // ... */ TypedByRef = 0x16, I = 0x18, // System.IntPtr U = 0x19, // System.UIntPtr FnPtr = 0x1b, // Followed by full method signature Object = 0x1c, // System.Object SzArray = 0x1d, // Single-dim array with 0 lower bound MVar = 0x1e, // Followed by generic parameter number CModReqD = 0x1f, // Required modifier : followed by a TypeDef or TypeRef token CModOpt = 0x20, // Optional modifier : followed by a TypeDef or TypeRef token Internal = 0x21, // Implemented within the CLI Modifier = 0x40, // Or'd with following element types Sentinel = 0x41, // Sentinel for varargs method signature Pinned = 0x45, // Denotes a local variable that points at a pinned object // special undocumented constants Type = 0x50, Boxed = 0x51, Enum = 0x55 } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/GuidHeap.cs ================================================ // // GuidHeap.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.PE; namespace Mono.Cecil.Metadata { sealed class GuidHeap : Heap { public GuidHeap (Section section, uint start, uint size) : base (section, start, size) { } public Guid Read (uint index) { if (index == 0) return new Guid (); const int guid_size = 16; var buffer = new byte [guid_size]; index--; Buffer.BlockCopy (Section.Data, (int) (Offset + index), buffer, 0, guid_size); return new Guid (buffer); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/Heap.cs ================================================ // // Heap.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using Mono.Cecil.PE; namespace Mono.Cecil.Metadata { abstract class Heap { public int IndexSize; public readonly Section Section; public readonly uint Offset; public readonly uint Size; protected Heap (Section section, uint offset, uint size) { this.Section = section; this.Offset = offset; this.Size = size; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/MetadataToken.cs ================================================ // // MetadataToken.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public struct MetadataToken { readonly uint token; public uint RID { get { return token & 0x00ffffff; } } public TokenType TokenType { get { return (TokenType) (token & 0xff000000); } } public static readonly MetadataToken Zero = new MetadataToken ((uint) 0); public MetadataToken (uint token) { this.token = token; } public MetadataToken (TokenType type) : this (type, 0) { } public MetadataToken (TokenType type, uint rid) { token = (uint) type | rid; } public MetadataToken (TokenType type, int rid) { token = (uint) type | (uint) rid; } public int ToInt32 () { return (int) token; } public uint ToUInt32 () { return token; } public override int GetHashCode () { return (int) token; } public override bool Equals (object obj) { if (obj is MetadataToken) { var other = (MetadataToken) obj; return other.token == token; } return false; } public static bool operator == (MetadataToken one, MetadataToken other) { return one.token == other.token; } public static bool operator != (MetadataToken one, MetadataToken other) { return one.token != other.token; } public override string ToString () { return string.Format ("[{0}:0x{1}]", TokenType, RID.ToString ("x4")); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/Row.cs ================================================ // // Row.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System.Collections.Generic; namespace Mono.Cecil.Metadata { class Row { internal T1 Col1; internal T2 Col2; public Row (T1 col1, T2 col2) { Col1 = col1; Col2 = col2; } } class Row { internal T1 Col1; internal T2 Col2; internal T3 Col3; public Row (T1 col1, T2 col2, T3 col3) { Col1 = col1; Col2 = col2; Col3 = col3; } } class Row { internal T1 Col1; internal T2 Col2; internal T3 Col3; internal T4 Col4; public Row (T1 col1, T2 col2, T3 col3, T4 col4) { Col1 = col1; Col2 = col2; Col3 = col3; Col4 = col4; } } class Row { internal T1 Col1; internal T2 Col2; internal T3 Col3; internal T4 Col4; internal T5 Col5; public Row (T1 col1, T2 col2, T3 col3, T4 col4, T5 col5) { Col1 = col1; Col2 = col2; Col3 = col3; Col4 = col4; Col5 = col5; } } class Row { internal T1 Col1; internal T2 Col2; internal T3 Col3; internal T4 Col4; internal T5 Col5; internal T6 Col6; public Row (T1 col1, T2 col2, T3 col3, T4 col4, T5 col5, T6 col6) { Col1 = col1; Col2 = col2; Col3 = col3; Col4 = col4; Col5 = col5; Col6 = col6; } } class Row { internal T1 Col1; internal T2 Col2; internal T3 Col3; internal T4 Col4; internal T5 Col5; internal T6 Col6; internal T7 Col7; internal T8 Col8; internal T9 Col9; public Row (T1 col1, T2 col2, T3 col3, T4 col4, T5 col5, T6 col6, T7 col7, T8 col8, T9 col9) { Col1 = col1; Col2 = col2; Col3 = col3; Col4 = col4; Col5 = col5; Col6 = col6; Col7 = col7; Col8 = col8; Col9 = col9; } } sealed class RowEqualityComparer : IEqualityComparer>, IEqualityComparer>, IEqualityComparer> { public bool Equals (Row x, Row y) { return x.Col1 == y.Col1 && x.Col2 == y.Col2; } public int GetHashCode (Row obj) { string x = obj.Col1, y = obj.Col2; return (x != null ? x.GetHashCode () : 0) ^ (y != null ? y.GetHashCode () : 0); } public bool Equals (Row x, Row y) { return x.Col1 == y.Col1 && x.Col2 == y.Col2; } public int GetHashCode (Row obj) { return (int) (obj.Col1 ^ obj.Col2); } public bool Equals (Row x, Row y) { return x.Col1 == y.Col1 && x.Col2 == y.Col2 && x.Col3 == y.Col3; } public int GetHashCode (Row obj) { return (int) (obj.Col1 ^ obj.Col2 ^ obj.Col3); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/StringHeap.cs ================================================ // // StringHeap.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using System.Text; using Mono.Cecil.PE; namespace Mono.Cecil.Metadata { class StringHeap : Heap { readonly Dictionary strings = new Dictionary (); public StringHeap (Section section, uint start, uint size) : base (section, start, size) { } public string Read (uint index) { if (index == 0) return string.Empty; string @string; if (strings.TryGetValue (index, out @string)) return @string; if (index > Size - 1) return string.Empty; @string = ReadStringAt (index); if (@string.Length != 0) strings.Add (index, @string); return @string; } protected virtual string ReadStringAt (uint index) { int length = 0; byte [] data = Section.Data; int start = (int) (index + Offset); for (int i = start; ; i++) { if (data [i] == 0) break; length++; } return Encoding.UTF8.GetString (data, start, length); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/TableHeap.cs ================================================ // // TableHeap.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.PE; namespace Mono.Cecil.Metadata { enum Table : byte { Module = 0x00, TypeRef = 0x01, TypeDef = 0x02, FieldPtr = 0x03, Field = 0x04, MethodPtr = 0x05, Method = 0x06, ParamPtr = 0x07, Param = 0x08, InterfaceImpl = 0x09, MemberRef = 0x0a, Constant = 0x0b, CustomAttribute = 0x0c, FieldMarshal = 0x0d, DeclSecurity = 0x0e, ClassLayout = 0x0f, FieldLayout = 0x10, StandAloneSig = 0x11, EventMap = 0x12, EventPtr = 0x13, Event = 0x14, PropertyMap = 0x15, PropertyPtr = 0x16, Property = 0x17, MethodSemantics = 0x18, MethodImpl = 0x19, ModuleRef = 0x1a, TypeSpec = 0x1b, ImplMap = 0x1c, FieldRVA = 0x1d, EncLog = 0x1e, EncMap = 0x1f, Assembly = 0x20, AssemblyProcessor = 0x21, AssemblyOS = 0x22, AssemblyRef = 0x23, AssemblyRefProcessor = 0x24, AssemblyRefOS = 0x25, File = 0x26, ExportedType = 0x27, ManifestResource = 0x28, NestedClass = 0x29, GenericParam = 0x2a, MethodSpec = 0x2b, GenericParamConstraint = 0x2c, } struct TableInformation { public uint Offset; public uint Length; public uint RowSize; } sealed class TableHeap : Heap { public long Valid; public long Sorted; public const int TableCount = 45; public readonly TableInformation [] Tables = new TableInformation [TableCount]; public TableInformation this [Table table] { get { return Tables [(int) table]; } } public TableHeap (Section section, uint start, uint size) : base (section, start, size) { } public bool HasTable (Table table) { return (Valid & (1L << (int) table)) != 0; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/TokenType.cs ================================================ // // TokenType.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // namespace Mono.Cecil { public enum TokenType : uint { Module = 0x00000000, TypeRef = 0x01000000, TypeDef = 0x02000000, Field = 0x04000000, Method = 0x06000000, Param = 0x08000000, InterfaceImpl = 0x09000000, MemberRef = 0x0a000000, CustomAttribute = 0x0c000000, Permission = 0x0e000000, Signature = 0x11000000, Event = 0x14000000, Property = 0x17000000, ModuleRef = 0x1a000000, TypeSpec = 0x1b000000, Assembly = 0x20000000, AssemblyRef = 0x23000000, File = 0x26000000, ExportedType = 0x27000000, ManifestResource = 0x28000000, GenericParam = 0x2a000000, MethodSpec = 0x2b000000, String = 0x70000000, } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/UserStringHeap.cs ================================================ // // UserStringHeap.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.PE; namespace Mono.Cecil.Metadata { sealed class UserStringHeap : StringHeap { public UserStringHeap(Section section, uint start, uint size) : base(section, start, size) { } protected override string ReadStringAt(uint index) { byte[] data = Section.Data; int start = (int)(index + Offset); uint length = (uint)(Mixin.ReadCompressedUInt32(data, ref start) & ~1); if (length < 1) return string.Empty; var chars = new char[length / 2]; for (int i = start, j = 0; i < start + length; i += 2) chars[j++] = (char)(data[i] | (data[i + 1] << 8)); return new string(chars); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.Metadata/Utilities.cs ================================================ // // Utilities.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono.Cecil.Metadata; namespace Mono.Cecil { static partial class Mixin { public static uint ReadCompressedUInt32(byte[] data, ref int position) { uint integer; if ((data[position] & 0x80) == 0) { integer = data[position]; position++; } else if ((data[position] & 0x40) == 0) { integer = (uint)(data[position] & ~0x80) << 8; integer |= data[position + 1]; position += 2; } else { integer = (uint)(data[position] & ~0xc0) << 24; integer |= (uint)data[position + 1] << 16; integer |= (uint)data[position + 2] << 8; integer |= (uint)data[position + 3]; position += 4; } return integer; } public static MetadataToken GetMetadataToken(CodedIndex self, uint data) { uint rid; TokenType token_type; switch (self) { case CodedIndex.TypeDefOrRef: rid = data >> 2; switch (data & 3) { case 0: token_type = TokenType.TypeDef; goto ret; case 1: token_type = TokenType.TypeRef; goto ret; case 2: token_type = TokenType.TypeSpec; goto ret; default: goto exit; } case CodedIndex.HasConstant: rid = data >> 2; switch (data & 3) { case 0: token_type = TokenType.Field; goto ret; case 1: token_type = TokenType.Param; goto ret; case 2: token_type = TokenType.Property; goto ret; default: goto exit; } case CodedIndex.HasCustomAttribute: rid = data >> 5; switch (data & 31) { case 0: token_type = TokenType.Method; goto ret; case 1: token_type = TokenType.Field; goto ret; case 2: token_type = TokenType.TypeRef; goto ret; case 3: token_type = TokenType.TypeDef; goto ret; case 4: token_type = TokenType.Param; goto ret; case 5: token_type = TokenType.InterfaceImpl; goto ret; case 6: token_type = TokenType.MemberRef; goto ret; case 7: token_type = TokenType.Module; goto ret; case 8: token_type = TokenType.Permission; goto ret; case 9: token_type = TokenType.Property; goto ret; case 10: token_type = TokenType.Event; goto ret; case 11: token_type = TokenType.Signature; goto ret; case 12: token_type = TokenType.ModuleRef; goto ret; case 13: token_type = TokenType.TypeSpec; goto ret; case 14: token_type = TokenType.Assembly; goto ret; case 15: token_type = TokenType.AssemblyRef; goto ret; case 16: token_type = TokenType.File; goto ret; case 17: token_type = TokenType.ExportedType; goto ret; case 18: token_type = TokenType.ManifestResource; goto ret; case 19: token_type = TokenType.GenericParam; goto ret; default: goto exit; } case CodedIndex.HasFieldMarshal: rid = data >> 1; switch (data & 1) { case 0: token_type = TokenType.Field; goto ret; case 1: token_type = TokenType.Param; goto ret; default: goto exit; } case CodedIndex.HasDeclSecurity: rid = data >> 2; switch (data & 3) { case 0: token_type = TokenType.TypeDef; goto ret; case 1: token_type = TokenType.Method; goto ret; case 2: token_type = TokenType.Assembly; goto ret; default: goto exit; } case CodedIndex.MemberRefParent: rid = data >> 3; switch (data & 7) { case 0: token_type = TokenType.TypeDef; goto ret; case 1: token_type = TokenType.TypeRef; goto ret; case 2: token_type = TokenType.ModuleRef; goto ret; case 3: token_type = TokenType.Method; goto ret; case 4: token_type = TokenType.TypeSpec; goto ret; default: goto exit; } case CodedIndex.HasSemantics: rid = data >> 1; switch (data & 1) { case 0: token_type = TokenType.Event; goto ret; case 1: token_type = TokenType.Property; goto ret; default: goto exit; } case CodedIndex.MethodDefOrRef: rid = data >> 1; switch (data & 1) { case 0: token_type = TokenType.Method; goto ret; case 1: token_type = TokenType.MemberRef; goto ret; default: goto exit; } case CodedIndex.MemberForwarded: rid = data >> 1; switch (data & 1) { case 0: token_type = TokenType.Field; goto ret; case 1: token_type = TokenType.Method; goto ret; default: goto exit; } case CodedIndex.Implementation: rid = data >> 2; switch (data & 3) { case 0: token_type = TokenType.File; goto ret; case 1: token_type = TokenType.AssemblyRef; goto ret; case 2: token_type = TokenType.ExportedType; goto ret; default: goto exit; } case CodedIndex.CustomAttributeType: rid = data >> 3; switch (data & 7) { case 2: token_type = TokenType.Method; goto ret; case 3: token_type = TokenType.MemberRef; goto ret; default: goto exit; } case CodedIndex.ResolutionScope: rid = data >> 2; switch (data & 3) { case 0: token_type = TokenType.Module; goto ret; case 1: token_type = TokenType.ModuleRef; goto ret; case 2: token_type = TokenType.AssemblyRef; goto ret; case 3: token_type = TokenType.TypeRef; goto ret; default: goto exit; } case CodedIndex.TypeOrMethodDef: rid = data >> 1; switch (data & 1) { case 0: token_type = TokenType.TypeDef; goto ret; case 1: token_type = TokenType.Method; goto ret; default: goto exit; } default: goto exit; } ret: return new MetadataToken(token_type, rid); exit: return MetadataToken.Zero; } public static int GetSize(CodedIndex self, Func counter) { int bits; Table[] tables; switch (self) { case CodedIndex.TypeDefOrRef: bits = 2; tables = new[] { Table.TypeDef, Table.TypeRef, Table.TypeSpec }; break; case CodedIndex.HasConstant: bits = 2; tables = new[] { Table.Field, Table.Param, Table.Property }; break; case CodedIndex.HasCustomAttribute: bits = 5; tables = new[] { Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef, Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef, Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType, Table.ManifestResource, Table.GenericParam }; break; case CodedIndex.HasFieldMarshal: bits = 1; tables = new[] { Table.Field, Table.Param }; break; case CodedIndex.HasDeclSecurity: bits = 2; tables = new[] { Table.TypeDef, Table.Method, Table.Assembly }; break; case CodedIndex.MemberRefParent: bits = 3; tables = new[] { Table.TypeDef, Table.TypeRef, Table.ModuleRef, Table.Method, Table.TypeSpec }; break; case CodedIndex.HasSemantics: bits = 1; tables = new[] { Table.Event, Table.Property }; break; case CodedIndex.MethodDefOrRef: bits = 1; tables = new[] { Table.Method, Table.MemberRef }; break; case CodedIndex.MemberForwarded: bits = 1; tables = new[] { Table.Field, Table.Method }; break; case CodedIndex.Implementation: bits = 2; tables = new[] { Table.File, Table.AssemblyRef, Table.ExportedType }; break; case CodedIndex.CustomAttributeType: bits = 3; tables = new[] { Table.Method, Table.MemberRef }; break; case CodedIndex.ResolutionScope: bits = 2; tables = new[] { Table.Module, Table.ModuleRef, Table.AssemblyRef, Table.TypeRef }; break; case CodedIndex.TypeOrMethodDef: bits = 1; tables = new[] { Table.TypeDef, Table.Method }; break; default: throw new ArgumentException(); } int max = 0; for (int i = 0; i < tables.Length; i++) { max = System.Math.Max(counter(tables[i]), max); } return max < (1 << (16 - bits)) ? 2 : 4; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/BinaryStreamReader.cs ================================================ // // BinaryStreamReader.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.IO; namespace Mono.Cecil.PE { class BinaryStreamReader : BinaryReader { public BinaryStreamReader (Stream stream) : base (stream) { } protected void Advance (int bytes) { BaseStream.Seek (bytes, SeekOrigin.Current); } protected DataDirectory ReadDataDirectory () { return new DataDirectory (ReadUInt32 (), ReadUInt32 ()); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/BinaryStreamWriter.cs ================================================ // // BinaryStreamWriter.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.IO; ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/ByteBuffer.cs ================================================ // // ByteBuffer.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; namespace Mono.Cecil.PE { class ByteBuffer { internal byte [] buffer; internal int length; internal int position; public ByteBuffer () { this.buffer = Empty.Array; } public ByteBuffer (int length) { this.buffer = new byte [length]; } public ByteBuffer (byte [] buffer) { this.buffer = buffer ?? Empty.Array; this.length = this.buffer.Length; } public void Reset (byte [] buffer) { this.buffer = buffer ?? Empty.Array; this.length = this.buffer.Length; } public void Advance (int length) { position += length; } public byte ReadByte () { return buffer [position++]; } public sbyte ReadSByte () { return (sbyte) ReadByte (); } public byte [] ReadBytes (int length) { var bytes = new byte [length]; Buffer.BlockCopy (buffer, position, bytes, 0, length); position += length; return bytes; } public ushort ReadUInt16 () { ushort value = (ushort) (buffer [position] | (buffer [position + 1] << 8)); position += 2; return value; } public short ReadInt16 () { return (short) ReadUInt16 (); } public uint ReadUInt32 () { uint value = (uint) (buffer [position] | (buffer [position + 1] << 8) | (buffer [position + 2] << 16) | (buffer [position + 3] << 24)); position += 4; return value; } public int ReadInt32 () { return (int) ReadUInt32 (); } public ulong ReadUInt64 () { uint low = ReadUInt32 (); uint high = ReadUInt32 (); return (((ulong) high) << 32) | low; } public long ReadInt64 () { return (long) ReadUInt64 (); } public uint ReadCompressedUInt32 () { byte first = ReadByte (); if ((first & 0x80) == 0) return first; if ((first & 0x40) == 0) return ((uint) (first & ~0x80) << 8) | ReadByte (); return ((uint) (first & ~0xc0) << 24) | (uint) ReadByte () << 16 | (uint) ReadByte () << 8 | ReadByte (); } public int ReadCompressedInt32 () { var value = (int) (ReadCompressedUInt32 () >> 1); if ((value & 1) == 0) return value; if (value < 0x40) return value - 0x40; if (value < 0x2000) return value - 0x2000; if (value < 0x10000000) return value - 0x10000000; return value - 0x20000000; } public float ReadSingle () { if (!BitConverter.IsLittleEndian) { var bytes = ReadBytes (4); Array.Reverse (bytes); return BitConverter.ToSingle (bytes, 0); } float value = BitConverter.ToSingle (buffer, position); position += 4; return value; } public double ReadDouble () { if (!BitConverter.IsLittleEndian) { var bytes = ReadBytes (8); Array.Reverse (bytes); return BitConverter.ToDouble (bytes, 0); } double value = BitConverter.ToDouble (buffer, position); position += 8; return value; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/ByteBufferEqualityComparer.cs ================================================ // // ByteBufferEqualityComparer.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; namespace Mono.Cecil.PE { sealed class ByteBufferEqualityComparer : IEqualityComparer { public bool Equals (ByteBuffer x, ByteBuffer y) { if (x.length != y.length) return false; var x_buffer = x.buffer; var y_buffer = y.buffer; for (int i = 0; i < x.length; i++) if (x_buffer [i] != y_buffer [i]) return false; return true; } public int GetHashCode (ByteBuffer buffer) { #if !BYTE_BUFFER_WELL_DISTRIBUTED_HASH var hash = 0; var bytes = buffer.buffer; for (int i = 0; i < buffer.length; i++) hash = (hash * 37) ^ bytes [i]; return hash; #else const uint p = 16777619; uint hash = 2166136261; var bytes = buffer.buffer; for (int i = 0; i < buffer.length; i++) hash = (hash ^ bytes [i]) * p; hash += hash << 13; hash ^= hash >> 7; hash += hash << 3; hash ^= hash >> 17; hash += hash << 5; return (int) hash; #endif } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/DataDirectory.cs ================================================ // // DataDirectory.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using RVA = System.UInt32; namespace Mono.Cecil.PE { struct DataDirectory { public readonly RVA VirtualAddress; public readonly uint Size; public bool IsZero { get { return VirtualAddress == 0 && Size == 0; } } public DataDirectory (RVA rva, uint size) { this.VirtualAddress = rva; this.Size = size; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/Image.cs ================================================ // // Image.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using Mono; using Mono.Cecil.Cil; using Mono.Cecil.Metadata; using RVA = System.UInt32; namespace Mono.Cecil.PE { sealed class Image { public ModuleKind Kind; public TargetRuntime Runtime; public TargetArchitecture Architecture; public ModuleCharacteristics Characteristics; public string FileName; public Section[] Sections; public Section MetadataSection; public uint EntryPointToken; public ModuleAttributes Attributes; public DataDirectory Debug; public DataDirectory Resources; public DataDirectory StrongName; public StringHeap StringHeap; public BlobHeap BlobHeap; public UserStringHeap UserStringHeap; public GuidHeap GuidHeap; public TableHeap TableHeap; readonly int[] coded_index_sizes = new int[13]; readonly Func counter; public Image() { counter = GetTableLength; } public bool HasTable(Table table) { return GetTableLength(table) > 0; } public int GetTableLength(Table table) { return (int)TableHeap[table].Length; } public int GetTableIndexSize(Table table) { return GetTableLength(table) < 65536 ? 2 : 4; } public int GetCodedIndexSize(CodedIndex coded_index) { var index = (int)coded_index; var size = coded_index_sizes[index]; if (size != 0) return size; return coded_index_sizes[index] = Mixin.GetSize(coded_index, counter); } public uint ResolveVirtualAddress(RVA rva) { var section = GetSectionAtVirtualAddress(rva); if (section == null) throw new ArgumentOutOfRangeException(); return ResolveVirtualAddressInSection(rva, section); } public uint ResolveVirtualAddressInSection(RVA rva, Section section) { return rva + section.PointerToRawData - section.VirtualAddress; } public Section GetSection(string name) { var sections = this.Sections; for (int i = 0; i < sections.Length; i++) { var section = sections[i]; if (section.Name == name) return section; } return null; } public Section GetSectionAtVirtualAddress(RVA rva) { var sections = this.Sections; for (int i = 0; i < sections.Length; i++) { var section = sections[i]; if (rva >= section.VirtualAddress && rva < section.VirtualAddress + section.SizeOfRawData) return section; } return null; } public ImageDebugDirectory GetDebugHeader(out byte[] header) { var section = GetSectionAtVirtualAddress(Debug.VirtualAddress); var buffer = new ByteBuffer(section.Data); buffer.position = (int)(Debug.VirtualAddress - section.VirtualAddress); var directory = new ImageDebugDirectory { Characteristics = buffer.ReadInt32(), TimeDateStamp = buffer.ReadInt32(), MajorVersion = buffer.ReadInt16(), MinorVersion = buffer.ReadInt16(), Type = buffer.ReadInt32(), SizeOfData = buffer.ReadInt32(), AddressOfRawData = buffer.ReadInt32(), PointerToRawData = buffer.ReadInt32(), }; buffer.position = (int)(directory.PointerToRawData - section.PointerToRawData); header = new byte[directory.SizeOfData]; Buffer.BlockCopy(buffer.buffer, buffer.position, header, 0, header.Length); return directory; } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/ImageReader.cs ================================================ // // ImageReader.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.IO; using Mono.Cecil.Metadata; using RVA = System.UInt32; namespace Mono.Cecil.PE { sealed class ImageReader : BinaryStreamReader { readonly Image image; DataDirectory cli; DataDirectory metadata; public ImageReader(Stream stream) : base(stream) { image = new Image(); image.FileName = Mixin.GetFullyQualifiedName(stream); } void MoveTo(DataDirectory directory) { BaseStream.Position = image.ResolveVirtualAddress(directory.VirtualAddress); } void MoveTo(uint position) { BaseStream.Position = position; } void ReadImage() { if (BaseStream.Length < 128) throw new BadImageFormatException(); // - DOSHeader // PE 2 // Start 58 // Lfanew 4 // End 64 if (ReadUInt16() != 0x5a4d) throw new BadImageFormatException(); Advance(58); MoveTo(ReadUInt32()); if (ReadUInt32() != 0x00004550) throw new BadImageFormatException(); // - PEFileHeader // Machine 2 image.Architecture = ReadArchitecture(); // NumberOfSections 2 ushort sections = ReadUInt16(); // TimeDateStamp 4 // PointerToSymbolTable 4 // NumberOfSymbols 4 // OptionalHeaderSize 2 Advance(14); // Characteristics 2 ushort characteristics = ReadUInt16(); ushort subsystem, dll_characteristics; ReadOptionalHeaders(out subsystem, out dll_characteristics); ReadSections(sections); ReadCLIHeader(); ReadMetadata(); image.Kind = GetModuleKind(characteristics, subsystem); image.Characteristics = (ModuleCharacteristics)dll_characteristics; } TargetArchitecture ReadArchitecture() { var machine = ReadUInt16(); switch (machine) { case 0x014c: return TargetArchitecture.I386; case 0x8664: return TargetArchitecture.AMD64; case 0x0200: return TargetArchitecture.IA64; case 0x01c4: return TargetArchitecture.ARMv7; } throw new NotSupportedException(); } static ModuleKind GetModuleKind(ushort characteristics, ushort subsystem) { if ((characteristics & 0x2000) != 0) // ImageCharacteristics.Dll return ModuleKind.Dll; if (subsystem == 0x2 || subsystem == 0x9) // SubSystem.WindowsGui || SubSystem.WindowsCeGui return ModuleKind.Windows; return ModuleKind.Console; } void ReadOptionalHeaders(out ushort subsystem, out ushort dll_characteristics) { // - PEOptionalHeader // - StandardFieldsHeader // Magic 2 bool pe64 = ReadUInt16() == 0x20b; // pe32 || pe64 // LMajor 1 // LMinor 1 // CodeSize 4 // InitializedDataSize 4 // UninitializedDataSize4 // EntryPointRVA 4 // BaseOfCode 4 // BaseOfData 4 || 0 // - NTSpecificFieldsHeader // ImageBase 4 || 8 // SectionAlignment 4 // FileAlignement 4 // OSMajor 2 // OSMinor 2 // UserMajor 2 // UserMinor 2 // SubSysMajor 2 // SubSysMinor 2 // Reserved 4 // ImageSize 4 // HeaderSize 4 // FileChecksum 4 Advance(66); // SubSystem 2 subsystem = ReadUInt16(); // DLLFlags 2 dll_characteristics = ReadUInt16(); // StackReserveSize 4 || 8 // StackCommitSize 4 || 8 // HeapReserveSize 4 || 8 // HeapCommitSize 4 || 8 // LoaderFlags 4 // NumberOfDataDir 4 // - DataDirectoriesHeader // ExportTable 8 // ImportTable 8 // ResourceTable 8 // ExceptionTable 8 // CertificateTable 8 // BaseRelocationTable 8 Advance(pe64 ? 88 : 72); // Debug 8 image.Debug = ReadDataDirectory(); // Copyright 8 // GlobalPtr 8 // TLSTable 8 // LoadConfigTable 8 // BoundImport 8 // IAT 8 // DelayImportDescriptor8 Advance(56); // CLIHeader 8 cli = ReadDataDirectory(); if (cli.IsZero) throw new BadImageFormatException(); // Reserved 8 Advance(8); } string ReadAlignedString(int length) { int read = 0; var buffer = new char[length]; while (read < length) { var current = ReadByte(); if (current == 0) break; buffer[read++] = (char)current; } Advance(-1 + ((read + 4) & ~3) - read); return new string(buffer, 0, read); } string ReadZeroTerminatedString(int length) { int read = 0; var buffer = new char[length]; var bytes = ReadBytes(length); while (read < length) { var current = bytes[read]; if (current == 0) break; buffer[read++] = (char)current; } return new string(buffer, 0, read); } void ReadSections(ushort count) { var sections = new Section[count]; for (int i = 0; i < count; i++) { var section = new Section(); // Name section.Name = ReadZeroTerminatedString(8); // VirtualSize 4 Advance(4); // VirtualAddress 4 section.VirtualAddress = ReadUInt32(); // SizeOfRawData 4 section.SizeOfRawData = ReadUInt32(); // PointerToRawData 4 section.PointerToRawData = ReadUInt32(); // PointerToRelocations 4 // PointerToLineNumbers 4 // NumberOfRelocations 2 // NumberOfLineNumbers 2 // Characteristics 4 Advance(16); sections[i] = section; ReadSectionData(section); } image.Sections = sections; } void ReadSectionData(Section section) { var position = BaseStream.Position; MoveTo(section.PointerToRawData); var length = (int)section.SizeOfRawData; var data = new byte[length]; int offset = 0, read; while ((read = Read(data, offset, length - offset)) > 0) offset += read; section.Data = data; BaseStream.Position = position; } void ReadCLIHeader() { MoveTo(cli); // - CLIHeader // Cb 4 // MajorRuntimeVersion 2 // MinorRuntimeVersion 2 Advance(8); // Metadata 8 metadata = ReadDataDirectory(); // Flags 4 image.Attributes = (ModuleAttributes)ReadUInt32(); // EntryPointToken 4 image.EntryPointToken = ReadUInt32(); // Resources 8 image.Resources = ReadDataDirectory(); // StrongNameSignature 8 image.StrongName = ReadDataDirectory(); // CodeManagerTable 8 // VTableFixups 8 // ExportAddressTableJumps 8 // ManagedNativeHeader 8 } void ReadMetadata() { MoveTo(metadata); if (ReadUInt32() != 0x424a5342) throw new BadImageFormatException(); // MajorVersion 2 // MinorVersion 2 // Reserved 4 Advance(8); var version = ReadZeroTerminatedString(ReadInt32()); image.Runtime = Mixin.ParseRuntime(version); // Flags 2 Advance(2); var streams = ReadUInt16(); var section = image.GetSectionAtVirtualAddress(metadata.VirtualAddress); if (section == null) throw new BadImageFormatException(); image.MetadataSection = section; for (int i = 0; i < streams; i++) ReadMetadataStream(section); if (image.TableHeap != null) ReadTableHeap(); } void ReadMetadataStream(Section section) { // Offset 4 uint start = metadata.VirtualAddress - section.VirtualAddress + ReadUInt32(); // relative to the section start // Size 4 uint size = ReadUInt32(); var name = ReadAlignedString(16); switch (name) { case "#~": case "#-": image.TableHeap = new TableHeap(section, start, size); break; case "#Strings": image.StringHeap = new StringHeap(section, start, size); break; case "#Blob": image.BlobHeap = new BlobHeap(section, start, size); break; case "#GUID": image.GuidHeap = new GuidHeap(section, start, size); break; case "#US": image.UserStringHeap = new UserStringHeap(section, start, size); break; } } void ReadTableHeap() { var heap = image.TableHeap; uint start = heap.Section.PointerToRawData; MoveTo(heap.Offset + start); // Reserved 4 // MajorVersion 1 // MinorVersion 1 Advance(6); // HeapSizes 1 var sizes = ReadByte(); // Reserved2 1 Advance(1); // Valid 8 heap.Valid = ReadInt64(); // Sorted 8 heap.Sorted = ReadInt64(); for (int i = 0; i < TableHeap.TableCount; i++) { if (!heap.HasTable((Table)i)) continue; heap.Tables[i].Length = ReadUInt32(); } SetIndexSize(image.StringHeap, sizes, 0x1); SetIndexSize(image.GuidHeap, sizes, 0x2); SetIndexSize(image.BlobHeap, sizes, 0x4); ComputeTableInformations(); } static void SetIndexSize(Heap heap, uint sizes, byte flag) { if (heap == null) return; heap.IndexSize = (sizes & flag) > 0 ? 4 : 2; } int GetTableIndexSize(Table table) { return image.GetTableIndexSize(table); } int GetCodedIndexSize(CodedIndex index) { return image.GetCodedIndexSize(index); } void ComputeTableInformations() { uint offset = (uint)BaseStream.Position - image.MetadataSection.PointerToRawData; // header int stridx_size = image.StringHeap.IndexSize; int blobidx_size = image.BlobHeap != null ? image.BlobHeap.IndexSize : 2; var heap = image.TableHeap; var tables = heap.Tables; for (int i = 0; i < TableHeap.TableCount; i++) { var table = (Table)i; if (!heap.HasTable(table)) continue; int size; switch (table) { case Table.Module: size = 2 // Generation + stridx_size // Name + (image.GuidHeap.IndexSize * 3); // Mvid, EncId, EncBaseId break; case Table.TypeRef: size = GetCodedIndexSize(CodedIndex.ResolutionScope) // ResolutionScope + (stridx_size * 2); // Name, Namespace break; case Table.TypeDef: size = 4 // Flags + (stridx_size * 2) // Name, Namespace + GetCodedIndexSize(CodedIndex.TypeDefOrRef) // BaseType + GetTableIndexSize(Table.Field) // FieldList + GetTableIndexSize(Table.Method); // MethodList break; case Table.FieldPtr: size = GetTableIndexSize(Table.Field); // Field break; case Table.Field: size = 2 // Flags + stridx_size // Name + blobidx_size; // Signature break; case Table.MethodPtr: size = GetTableIndexSize(Table.Method); // Method break; case Table.Method: size = 8 // Rva 4, ImplFlags 2, Flags 2 + stridx_size // Name + blobidx_size // Signature + GetTableIndexSize(Table.Param); // ParamList break; case Table.ParamPtr: size = GetTableIndexSize(Table.Param); // Param break; case Table.Param: size = 4 // Flags 2, Sequence 2 + stridx_size; // Name break; case Table.InterfaceImpl: size = GetTableIndexSize(Table.TypeDef) // Class + GetCodedIndexSize(CodedIndex.TypeDefOrRef); // Interface break; case Table.MemberRef: size = GetCodedIndexSize(CodedIndex.MemberRefParent) // Class + stridx_size // Name + blobidx_size; // Signature break; case Table.Constant: size = 2 // Type + GetCodedIndexSize(CodedIndex.HasConstant) // Parent + blobidx_size; // Value break; case Table.CustomAttribute: size = GetCodedIndexSize(CodedIndex.HasCustomAttribute) // Parent + GetCodedIndexSize(CodedIndex.CustomAttributeType) // Type + blobidx_size; // Value break; case Table.FieldMarshal: size = GetCodedIndexSize(CodedIndex.HasFieldMarshal) // Parent + blobidx_size; // NativeType break; case Table.DeclSecurity: size = 2 // Action + GetCodedIndexSize(CodedIndex.HasDeclSecurity) // Parent + blobidx_size; // PermissionSet break; case Table.ClassLayout: size = 6 // PackingSize 2, ClassSize 4 + GetTableIndexSize(Table.TypeDef); // Parent break; case Table.FieldLayout: size = 4 // Offset + GetTableIndexSize(Table.Field); // Field break; case Table.StandAloneSig: size = blobidx_size; // Signature break; case Table.EventMap: size = GetTableIndexSize(Table.TypeDef) // Parent + GetTableIndexSize(Table.Event); // EventList break; case Table.EventPtr: size = GetTableIndexSize(Table.Event); // Event break; case Table.Event: size = 2 // Flags + stridx_size // Name + GetCodedIndexSize(CodedIndex.TypeDefOrRef); // EventType break; case Table.PropertyMap: size = GetTableIndexSize(Table.TypeDef) // Parent + GetTableIndexSize(Table.Property); // PropertyList break; case Table.PropertyPtr: size = GetTableIndexSize(Table.Property); // Property break; case Table.Property: size = 2 // Flags + stridx_size // Name + blobidx_size; // Type break; case Table.MethodSemantics: size = 2 // Semantics + GetTableIndexSize(Table.Method) // Method + GetCodedIndexSize(CodedIndex.HasSemantics); // Association break; case Table.MethodImpl: size = GetTableIndexSize(Table.TypeDef) // Class + GetCodedIndexSize(CodedIndex.MethodDefOrRef) // MethodBody + GetCodedIndexSize(CodedIndex.MethodDefOrRef); // MethodDeclaration break; case Table.ModuleRef: size = stridx_size; // Name break; case Table.TypeSpec: size = blobidx_size; // Signature break; case Table.ImplMap: size = 2 // MappingFlags + GetCodedIndexSize(CodedIndex.MemberForwarded) // MemberForwarded + stridx_size // ImportName + GetTableIndexSize(Table.ModuleRef); // ImportScope break; case Table.FieldRVA: size = 4 // RVA + GetTableIndexSize(Table.Field); // Field break; case Table.EncLog: case Table.EncMap: size = 4; break; case Table.Assembly: size = 16 // HashAlgId 4, Version 4 * 2, Flags 4 + blobidx_size // PublicKey + (stridx_size * 2); // Name, Culture break; case Table.AssemblyProcessor: size = 4; // Processor break; case Table.AssemblyOS: size = 12; // Platform 4, Version 2 * 4 break; case Table.AssemblyRef: size = 12 // Version 2 * 4 + Flags 4 + (blobidx_size * 2) // PublicKeyOrToken, HashValue + (stridx_size * 2); // Name, Culture break; case Table.AssemblyRefProcessor: size = 4 // Processor + GetTableIndexSize(Table.AssemblyRef); // AssemblyRef break; case Table.AssemblyRefOS: size = 12 // Platform 4, Version 2 * 4 + GetTableIndexSize(Table.AssemblyRef); // AssemblyRef break; case Table.File: size = 4 // Flags + stridx_size // Name + blobidx_size; // HashValue break; case Table.ExportedType: size = 8 // Flags 4, TypeDefId 4 + (stridx_size * 2) // Name, Namespace + GetCodedIndexSize(CodedIndex.Implementation); // Implementation break; case Table.ManifestResource: size = 8 // Offset, Flags + stridx_size // Name + GetCodedIndexSize(CodedIndex.Implementation); // Implementation break; case Table.NestedClass: size = GetTableIndexSize(Table.TypeDef) // NestedClass + GetTableIndexSize(Table.TypeDef); // EnclosingClass break; case Table.GenericParam: size = 4 // Number, Flags + GetCodedIndexSize(CodedIndex.TypeOrMethodDef) // Owner + stridx_size; // Name break; case Table.MethodSpec: size = GetCodedIndexSize(CodedIndex.MethodDefOrRef) // Method + blobidx_size; // Instantiation break; case Table.GenericParamConstraint: size = GetTableIndexSize(Table.GenericParam) // Owner + GetCodedIndexSize(CodedIndex.TypeDefOrRef); // Constraint break; default: throw new NotSupportedException(); } tables[i].RowSize = (uint)size; tables[i].Offset = offset; offset += (uint)size * tables[i].Length; } } public static Image ReadImageFrom(Stream stream) { try { var reader = new ImageReader(stream); reader.ReadImage(); return reader.image; } catch (EndOfStreamException e) { throw new BadImageFormatException(Mixin.GetFullyQualifiedName(stream), e); } } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/ImageWriter.cs ================================================ ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/Section.cs ================================================ // // Section.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using RVA = System.UInt32; namespace Mono.Cecil.PE { sealed class Section { public string Name; public RVA VirtualAddress; public uint VirtualSize; public uint SizeOfRawData; public uint PointerToRawData; public byte [] Data; } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Cecil.PE/TextMap.cs ================================================ ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Collections.Generic/Collection.cs ================================================ // // Collection.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections; using System.Collections.Generic; namespace Mono.Collections.Generic { public class Collection : IList, IList { internal T [] items; internal int size; int version; public int Count { get { return size; } } public T this [int index] { get { if (index >= size) throw new ArgumentOutOfRangeException (); return items [index]; } set { CheckIndex (index); if (index == size) throw new ArgumentOutOfRangeException (); OnSet (value, index); items [index] = value; } } bool ICollection.IsReadOnly { get { return false; } } bool IList.IsFixedSize { get { return false; } } bool IList.IsReadOnly { get { return false; } } object IList.this [int index] { get { return this [index]; } set { CheckIndex (index); try { this [index] = (T) value; return; } catch (InvalidCastException) { } catch (NullReferenceException) { } throw new ArgumentException (); } } int ICollection.Count { get { return Count; } } bool ICollection.IsSynchronized { get { return false; } } object ICollection.SyncRoot { get { return this; } } public Collection () { items = Empty.Array; } public Collection (int capacity) { if (capacity < 0) throw new ArgumentOutOfRangeException (); items = new T [capacity]; } public Collection (ICollection items) { if (items == null) throw new ArgumentNullException ("items"); this.items = new T [items.Count]; items.CopyTo (this.items, 0); this.size = this.items.Length; } public void Add (T item) { if (size == items.Length) Grow (1); OnAdd (item, size); items [size++] = item; version++; } public bool Contains (T item) { return IndexOf (item) != -1; } public int IndexOf (T item) { return Array.IndexOf (items, item, 0, size); } public void Insert (int index, T item) { CheckIndex (index); if (size == items.Length) Grow (1); OnInsert (item, index); Shift (index, 1); items [index] = item; version++; } public void RemoveAt (int index) { if (index < 0 || index >= size) throw new ArgumentOutOfRangeException (); var item = items [index]; OnRemove (item, index); Shift (index, -1); Array.Clear (items, size, 1); version++; } public bool Remove (T item) { var index = IndexOf (item); if (index == -1) return false; OnRemove (item, index); Shift (index, -1); Array.Clear (items, size, 1); version++; return true; } public void Clear () { OnClear (); Array.Clear (items, 0, size); size = 0; version++; } public void CopyTo (T [] array, int arrayIndex) { Array.Copy (items, 0, array, arrayIndex, size); } public T [] ToArray () { var array = new T [size]; Array.Copy (items, 0, array, 0, size); return array; } void CheckIndex (int index) { if (index < 0 || index > size) throw new ArgumentOutOfRangeException (); } void Shift (int start, int delta) { if (delta < 0) start -= delta; if (start < size) Array.Copy (items, start, items, start + delta, size - start); size += delta; if (delta < 0) Array.Clear (items, size, -delta); } protected virtual void OnAdd (T item, int index) { } protected virtual void OnInsert (T item, int index) { } protected virtual void OnSet (T item, int index) { } protected virtual void OnRemove (T item, int index) { } protected virtual void OnClear () { } internal virtual void Grow (int desired) { int new_size = size + desired; if (new_size <= items.Length) return; const int default_capacity = 4; new_size = System.Math.Max ( System.Math.Max (items.Length * 2, default_capacity), new_size); #if !CF Array.Resize (ref items, new_size); #else var array = new T [new_size]; Array.Copy (items, array, size); items = array; #endif } int IList.Add (object value) { try { Add ((T) value); return size - 1; } catch (InvalidCastException) { } catch (NullReferenceException) { } throw new ArgumentException (); } void IList.Clear () { Clear (); } bool IList.Contains (object value) { return ((IList) this).IndexOf (value) > -1; } int IList.IndexOf (object value) { try { return IndexOf ((T) value); } catch (InvalidCastException) { } catch (NullReferenceException) { } return -1; } void IList.Insert (int index, object value) { CheckIndex (index); try { Insert (index, (T) value); return; } catch (InvalidCastException) { } catch (NullReferenceException) { } throw new ArgumentException (); } void IList.Remove (object value) { try { Remove ((T) value); } catch (InvalidCastException) { } catch (NullReferenceException) { } } void IList.RemoveAt (int index) { RemoveAt (index); } void ICollection.CopyTo (Array array, int index) { Array.Copy (items, 0, array, index, size); } public Enumerator GetEnumerator () { return new Enumerator (this); } IEnumerator IEnumerable.GetEnumerator () { return new Enumerator (this); } IEnumerator IEnumerable.GetEnumerator () { return new Enumerator (this); } public struct Enumerator : IEnumerator, IDisposable { Collection collection; T current; int next; readonly int version; public T Current { get { return current; } } object IEnumerator.Current { get { CheckState (); if (next <= 0) throw new InvalidOperationException (); return current; } } internal Enumerator (Collection collection) : this () { this.collection = collection; this.version = collection.version; } public bool MoveNext () { CheckState (); if (next < 0) return false; if (next < collection.size) { current = collection.items [next++]; return true; } next = -1; return false; } public void Reset () { CheckState (); next = 0; } void CheckState () { if (collection == null) throw new ObjectDisposedException (GetType ().FullName); if (version != collection.version) throw new InvalidOperationException (); } public void Dispose () { collection = null; } } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Collections.Generic/ReadOnlyCollection.cs ================================================ // // ReadOnlyCollection.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections; using System .Collections.Generic; namespace Mono.Collections.Generic { public sealed class ReadOnlyCollection : Collection, ICollection, IList { static ReadOnlyCollection empty; public static ReadOnlyCollection Empty { get { return empty ?? (empty = new ReadOnlyCollection ()); } } bool ICollection.IsReadOnly { get { return true; } } bool IList.IsFixedSize { get { return true; } } bool IList.IsReadOnly { get { return true; } } private ReadOnlyCollection () { } public ReadOnlyCollection (T [] array) { if (array == null) throw new ArgumentNullException (); Initialize (array, array.Length); } public ReadOnlyCollection (Collection collection) { if (collection == null) throw new ArgumentNullException (); Initialize (collection.items, collection.size); } void Initialize (T [] items, int size) { this.items = new T [size]; Array.Copy (items, 0, this.items, 0, size); this.size = size; } internal override void Grow (int desired) { throw new InvalidOperationException (); } protected override void OnAdd (T item, int index) { throw new InvalidOperationException (); } protected override void OnClear () { throw new InvalidOperationException (); } protected override void OnInsert (T item, int index) { throw new InvalidOperationException (); } protected override void OnRemove (T item, int index) { throw new InvalidOperationException (); } protected override void OnSet (T item, int index) { throw new InvalidOperationException (); } } } ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Security.Cryptography/CryptoConvert.cs ================================================ ================================================ FILE: SGFUnity/Mono.Cecil.20/MonoCecil/Mono.Security.Cryptography/CryptoService.cs ================================================ // // CryptoService.cs // // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.IO; using System.Reflection; using System.Security.Cryptography; ================================================ FILE: SGFUnity/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // 有关程序集的一般信息由以下 // 控制。更改这些特性值可修改 // 与程序集关联的信息。 [assembly: AssemblyTitle("SGFUnity")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("HP Inc.")] [assembly: AssemblyProduct("SGFUnity")] [assembly: AssemblyCopyright("Copyright © HP Inc. 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // 将 ComVisible 设置为 false 会使此程序集中的类型 //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 //请将此类型的 ComVisible 特性设置为 true。 [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID [assembly: Guid("64ecff78-ee1f-432b-a581-a70e8eb6de83")] // 程序集的版本信息由下列四个值组成: // // 主版本 // 次版本 // 生成号 // 修订号 // // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 //通过使用 "*",如下所示: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: SGFUnity/SGFUnity.csproj ================================================  Debug AnyCPU {64ECFF78-EE1F-432B-A581-A70E8EB6DE83} Library Properties SGF.Unity SGFUnity v3.5 512 true full false ..\Libs\ TRACE;DEBUG;ENABLE_LOG prompt 4 true pdbonly true ..\Libs\ TRACE;ENABLE_LOG prompt 4 true False ..\Libs\Common\protobuf-net.dll False ..\Libs\SGFCore.dll False ..\Libs\SGFDebuger.dll False ..\Libs\Common\UnityEngine.dll False ..\Libs\Common\UnityEngine.UI.dll False ..\Libs\Common\zxing.unity.dll $(ProjectDir)..\Libs\PublishLibrary.bat $(TargetName) ================================================ FILE: SGFUnity/SGFUnity.csproj.user ================================================  ProjectFiles ================================================ FILE: SGFUnity/UI/Drag/Draggable.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; namespace SGF.Unity.UI.Drag { public class Draggable:MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler { public static GameObject HolderPrefab; private DropZone m_zone; private DropZone m_holderZone; private GameObject m_holder; public void OnBeginDrag(PointerEventData eventData) { if (HolderPrefab == null) { m_holder = new GameObject(this.name + "(Holder)"); } else { m_holder = GameObject.Instantiate(HolderPrefab); m_holder.name = this.name + "(Holder)"; } m_holder.transform.SetParent(this.transform.parent); m_holder.transform.SetSiblingIndex(this.transform.GetSiblingIndex()); if (this.GetComponent() != null) { LayoutElement le = m_holder.AddComponent(); le.preferredWidth = this.GetComponent().preferredWidth; le.preferredHeight = this.GetComponent().preferredHeight; le.flexibleWidth = 0; le.flexibleHeight = 0; } m_zone = this.transform.parent.GetComponent(); m_holderZone = m_zone; //如果开始拖动,将它移出公共区域 this.transform.SetParent(this.transform.parent.parent); SetBlocksRaycasts(false); } public void OnDrag(PointerEventData eventData) { this.transform.position = eventData.position; //在 拖动过程中,可以会经过一些Zone if (m_holderZone != null) { if (m_holder.transform.parent != m_holderZone) { m_holder.transform.SetParent(m_holderZone.transform); } int newSiblingIndex = m_holderZone.transform.childCount; for (int i = 0; i < m_holderZone.transform.childCount; i++) { if (this.transform.position.x < m_holderZone.transform.GetChild(i).position.x) { newSiblingIndex = i; if (m_holder.transform.GetSiblingIndex() < newSiblingIndex) newSiblingIndex--; break; } } m_holder.transform.SetSiblingIndex(newSiblingIndex); } } public virtual void OnEndDrag(PointerEventData eventData) { this.transform.SetParent(m_zone.transform); this.transform.SetSiblingIndex(m_holder.transform.GetSiblingIndex()); SetBlocksRaycasts(true); Destroy(m_holder); } public void EnterZone(DropZone zone) { m_holderZone = zone; } public void ExitZone(DropZone zone) { if (m_holderZone == zone) { m_holderZone = m_zone; } } public void DropZone(DropZone zone) { m_zone.OnDropOut(this); m_zone = zone; m_zone.OnDropIn(this); } private void SetBlocksRaycasts(bool value) { var group = this.GetComponent(); if (group != null) { group.blocksRaycasts = value; } } } } ================================================ FILE: SGFUnity/UI/Drag/DropZone.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using UnityEngine; using UnityEngine.EventSystems; namespace SGF.Unity.UI.Drag { public class DropZone:MonoBehaviour, IDropHandler, IPointerEnterHandler, IPointerExitHandler { public virtual void OnDrop(PointerEventData eventData) { Draggable d = eventData.pointerDrag.GetComponent(); if (d != null) { d.DropZone(this); } } public void OnPointerEnter(PointerEventData eventData) { if (eventData.pointerDrag == null) return; Draggable d = eventData.pointerDrag.GetComponent(); if (d != null) { d.EnterZone(this); } } public void OnPointerExit(PointerEventData eventData) { if (eventData.pointerDrag == null) return; Draggable d = eventData.pointerDrag.GetComponent(); if (d != null) { d.ExitZone(this); } } public virtual void OnDropIn(Draggable item) { } public virtual void OnDropOut(Draggable item) { } } } ================================================ FILE: SGFUnity/UI/SGUI/Drawing.cs ================================================ using System.Reflection; using UnityEngine; // Line drawing routine originally courtesy of Linusmartensson: // http://forum.unity3d.com/threads/71979-Drawing-lines-in-the-editor // // Rewritten to improve performance by Yossarian King / August 2013. // // This version produces virtually identical results to the original (tested by drawing // one over the other and observing errors of one pixel or less), but for large numbers // of lines this version is more than four times faster than the original, and comes // within about 70% of the raw performance of Graphics.DrawTexture. // // Peak performance on my laptop is around 200,000 lines per second. The laptop is // Windows 7 64-bit, Intel Core2 Duo CPU 2.53GHz, 4G RAM, NVIDIA GeForce GT 220M. // Line width and anti-aliasing had negligible impact on performance. // // For a graph of benchmark results in a standalone Windows build, see this image: // https://app.box.com/s/hyuhi565dtolqdm97e00 // // For a Google spreadsheet with full benchmark results, see: // https://docs.google.com/spreadsheet/ccc?key=0AvJlJlbRO26VdHhzeHNRMVF2UHZHMXFCTVFZN011V1E&usp=sharing public static class Drawing { private static Texture2D aaLineTex = null; private static Texture2D lineTex = null; private static Material blitMaterial = null; private static Material blendMaterial = null; private static Rect lineRect = new Rect(0, 0, 1, 1); // This static initializer works for runtime, but apparently isn't called when // Editor play mode stops, so DrawLine will re-initialize if needed. static Drawing() { Init(); } private static void Init() { if (lineTex == null) { lineTex = new Texture2D(1, 1, TextureFormat.ARGB32, false); lineTex.SetPixel(0, 1, Color.white); lineTex.Apply(); } if (aaLineTex == null) { // TODO: better anti-aliasing of wide lines with a larger texture? or use Graphics.DrawTexture with border settings aaLineTex = new Texture2D(1, 3, TextureFormat.ARGB32, false); aaLineTex.SetPixel(0, 0, new Color(1, 1, 1, 0)); aaLineTex.SetPixel(0, 1, Color.white); aaLineTex.SetPixel(0, 2, new Color(1, 1, 1, 0)); aaLineTex.Apply(); } // GUI.blitMaterial and GUI.blendMaterial are used internally by GUI.DrawTexture, // depending on the alphaBlend parameter. Use reflection to "borrow" these references. blitMaterial = (Material)typeof(GUI).GetMethod("get_blitMaterial", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, null); blendMaterial = (Material)typeof(GUI).GetMethod("get_blendMaterial", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, null); } // Draw a line in screen space, suitable for use from OnGUI calls from either // MonoBehaviour or EditorWindow. Note that this should only be called during repaint // events, when (Event.current.type == EventType.Repaint). // // Works by computing a matrix that transforms a unit square -- Rect(0,0,1,1) -- into // a scaled, rotated, and offset rectangle that corresponds to the line and its width. // A DrawTexture call used to draw a line texture into the transformed rectangle. // // More specifically: // scale x by line length, y by line width // rotate around z by the angle of the line // offset by the position of the upper left corner of the target rectangle // // By working out the matrices and applying some trigonometry, the matrix calculation comes // out pretty simple. See https://app.box.com/s/xi08ow8o8ujymazg100j for a picture of my // notebook with the calculations. public static void DrawLine(Vector2 pointA, Vector2 pointB, Color color, float width, bool antiAlias) { // Normally the static initializer does this, but to handle texture reinitialization // after editor play mode stops we need this check in the Editor. #if UNITY_EDITOR if (!lineTex) { Initialize(); } #endif // Note that theta = atan2(dy, dx) is the angle we want to rotate by, but instead // of calculating the angle we just use the sine (dy/len) and cosine (dx/len). float dx = pointB.x - pointA.x; float dy = pointB.y - pointA.y; float len = Mathf.Sqrt(dx * dx + dy * dy); // Early out on tiny lines to avoid divide by zero. // Plus what's the point of drawing a line 1/1000th of a pixel long?? if (len < 0.001f) { return; } // Pick texture and material (and tweak width) based on anti-alias setting. Texture2D tex; Material mat; if (antiAlias) { // Multiplying by three is fine for anti-aliasing width-1 lines, but make a wide "fringe" // for thicker lines, which may or may not be desirable. width = width * 3.0f; tex = aaLineTex; mat = blendMaterial; } else { tex = lineTex; mat = blitMaterial; } float wdx = width * dy / len; float wdy = width * dx / len; Matrix4x4 matrix = Matrix4x4.identity; matrix.m00 = dx; matrix.m01 = -wdx; matrix.m03 = pointA.x + 0.5f * wdx; matrix.m10 = dy; matrix.m11 = wdy; matrix.m13 = pointA.y - 0.5f * wdy; // Use GL matrix and Graphics.DrawTexture rather than GUI.matrix and GUI.DrawTexture, // for better performance. (Setting GUI.matrix is slow, and GUI.DrawTexture is just a // wrapper on Graphics.DrawTexture.) GL.PushMatrix(); GL.MultMatrix(matrix); //Graphics.DrawTexture(lineRect, tex, lineRect, 0, 0, 0, 0, color, mat); //Replaced by: GUI.color = color;//this and... GUI.DrawTexture(lineRect, tex);//this GL.PopMatrix(); } public static void DrawCircle(Vector2 center, int radius, Color color, float width, int segmentsPerQuarter) { DrawCircle(center, radius, color, width, false, segmentsPerQuarter); } public static void DrawCircle(Vector2 center, int radius, Color color, float width, bool antiAlias, int segmentsPerQuarter) { float rh = (float)radius / 2; Vector2 p1 = new Vector2(center.x, center.y - radius); Vector2 p1_tan_a = new Vector2(center.x - rh, center.y - radius); Vector2 p1_tan_b = new Vector2(center.x + rh, center.y - radius); Vector2 p2 = new Vector2(center.x + radius, center.y); Vector2 p2_tan_a = new Vector2(center.x + radius, center.y - rh); Vector2 p2_tan_b = new Vector2(center.x + radius, center.y + rh); Vector2 p3 = new Vector2(center.x, center.y + radius); Vector2 p3_tan_a = new Vector2(center.x - rh, center.y + radius); Vector2 p3_tan_b = new Vector2(center.x + rh, center.y + radius); Vector2 p4 = new Vector2(center.x - radius, center.y); Vector2 p4_tan_a = new Vector2(center.x - radius, center.y - rh); Vector2 p4_tan_b = new Vector2(center.x - radius, center.y + rh); DrawBezierLine(p1, p1_tan_b, p2, p2_tan_a, color, width, antiAlias, segmentsPerQuarter); DrawBezierLine(p2, p2_tan_b, p3, p3_tan_b, color, width, antiAlias, segmentsPerQuarter); DrawBezierLine(p3, p3_tan_a, p4, p4_tan_b, color, width, antiAlias, segmentsPerQuarter); DrawBezierLine(p4, p4_tan_a, p1, p1_tan_a, color, width, antiAlias, segmentsPerQuarter); } // Other than method name, DrawBezierLine is unchanged from Linusmartensson's original implementation. public static void DrawBezierLine(Vector2 start, Vector2 startTangent, Vector2 end, Vector2 endTangent, Color color, float width, bool antiAlias, int segments) { Vector2 lastV = CubeBezier(start, startTangent, end, endTangent, 0); for (int i = 1; i < segments + 1; ++i) { Vector2 v = CubeBezier(start, startTangent, end, endTangent, i / (float)segments); DrawLine(lastV, v, color, width, antiAlias); lastV = v; } } private static Vector2 CubeBezier(Vector2 s, Vector2 st, Vector2 e, Vector2 et, float t) { float rt = 1 - t; return rt * rt * rt * s + 3 * rt * rt * t * st + 3 * rt * t * t * et + t * t * t * e; } } ================================================ FILE: SGFUnity/UI/SGUI/DrawingSimple.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine; public class DrawingSimple { //**************************************************************************************************** // static function DrawLine(rect : Rect) : void // static function DrawLine(rect : Rect, color : Color) : void // static function DrawLine(rect : Rect, width : float) : void // static function DrawLine(rect : Rect, color : Color, width : float) : void // static function DrawLine(Vector2 pointA, Vector2 pointB) : void // static function DrawLine(Vector2 pointA, Vector2 pointB, color : Color) : void // static function DrawLine(Vector2 pointA, Vector2 pointB, width : float) : void // static function DrawLine(Vector2 pointA, Vector2 pointB, color : Color, width : float) : void // // Draws a GUI line on the screen. // // DrawLine makes up for the severe lack of 2D line rendering in the Unity runtime GUI system. // This function works by drawing a 1x1 texture filled with a color, which is then scaled // and rotated by altering the GUI matrix. The matrix is restored afterwards. //**************************************************************************************************** public static Texture2D lineTex; public static void DrawLine(Rect rect) { DrawLine(rect, GUI.contentColor, 1.0f); } public static void DrawLine(Rect rect, Color color) { DrawLine(rect, color, 1.0f); } public static void DrawLine(Rect rect, float width) { DrawLine(rect, GUI.contentColor, width); } public static void DrawLine(Rect rect, Color color, float width) { DrawLine(new Vector2(rect.x, rect.y), new Vector2(rect.x + rect.width, rect.y + rect.height), color, width); } public static void DrawLine(Vector2 pointA, Vector2 pointB) { DrawLine(pointA, pointB, GUI.contentColor, 1.0f); } public static void DrawLine(Vector2 pointA, Vector2 pointB, Color color) { DrawLine(pointA, pointB, color, 1.0f); } public static void DrawLine(Vector2 pointA, Vector2 pointB, float width) { DrawLine(pointA, pointB, GUI.contentColor, width); } public static void DrawLine(Vector2 pointA, Vector2 pointB, Color color, float width) { // Save the current GUI matrix, since we're going to make changes to it. Matrix4x4 matrix = GUI.matrix; // Generate a single pixel texture if it doesn't exist if (!lineTex) { lineTex = new Texture2D(1, 1); } // Store current GUI color, so we can switch it back later, // and set the GUI color to the color parameter Color savedColor = GUI.color; GUI.color = color; // Determine the angle of the line. float angle = Vector3.Angle(pointB - pointA, Vector2.right); // Vector3.Angle always returns a positive number. // If pointB is above pointA, then angle needs to be negative. if (pointA.y > pointB.y) { angle = -angle; } // Use ScaleAroundPivot to adjust the size of the line. // We could do this when we draw the texture, but by scaling it here we can use // non-integer values for the width and length (such as sub 1 pixel widths). // Note that the pivot point is at +.5 from pointA.y, this is so that the width of the line // is centered on the origin at pointA. GUIUtility.ScaleAroundPivot(new Vector2((pointB - pointA).magnitude, width), new Vector2(pointA.x, pointA.y + 0.5f)); // Set the rotation for the line. // The angle was calculated with pointA as the origin. GUIUtility.RotateAroundPivot(angle, pointA); // Finally, draw the actual line. // We're really only drawing a 1x1 texture from pointA. // The matrix operations done with ScaleAroundPivot and RotateAroundPivot will make this // render with the proper width, length, and angle. GUI.DrawTexture(new Rect(pointA.x, pointA.y, 1, 1), lineTex); // We're done. Restore the GUI matrix and GUI color to whatever they were before. GUI.matrix = matrix; GUI.color = savedColor; } } ================================================ FILE: SGFUnity/UI/SGUI/GUICurve.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System.Collections.Generic; using UnityEngine; namespace SGF.Unity.UI.SGUI { public class GUICurve { public bool AntiAlias = false; public object state = null; private List m_source; private float m_maxX = float.MinValue; private float m_minX = float.MaxValue; private float m_maxY = float.MinValue; private float m_minY = float.MaxValue; public float MinX { get { return m_minX; } } public float MinY { get { return m_minY; } } public float MaxX { get { return m_maxX; } } public float MaxY { get { return m_maxY; } } public GUICurve(List source) { m_source = new List(); if (source != null) { for (int i = 0; i < source.Count; i++) { AddPoint(source[i]); } } } public GUICurve() { m_source = new List(); } public int Length { get { return m_source.Count; } } public List Source { get { return m_source; } } public void SetRangeY(float min, float max) { m_minY = min; m_maxY = max; } public void AddPoint(Vector2 point) { m_source.Add(point); if (m_maxX < point.x) { m_maxX = point.x; } if (m_maxY < point.y) { m_maxY = point.y; } if (m_minX > point.x) { m_minX = point.x; } if (m_minY > point.y) { m_minY = point.y; } } public void AddRangePoint(List listPoints) { if (listPoints == null || listPoints.Count == 0) { return; } for (int i = 0; i < listPoints.Count; i++) { AddPoint(listPoints[i]); } } public void Clear() { m_maxX = float.MinValue; m_minX = float.MaxValue; m_maxY = float.MinValue; m_minY = float.MaxValue; m_source.Clear(); } //================================================================================== public Color lineColor = Color.red; public Color pointColor = Color.red; public int lineWidth = 2; public int pointRadius = 0; public int minScope = 0; public int maxScope = 0; public void Draw(Rect rect, Color color, int width, int minScope = 0, int maxScope = 0) { Draw(rect, color, width, Color.white, 0, minScope, maxScope); } public void Draw(Rect rect, Color color, int width, Color pointColor, int pointRadius, int minScope = 0, int maxScope = 0) { if (m_source == null || m_source.Count < 2) { return; } if (minScope < 0 || minScope >= m_source.Count) { minScope = 0; } if (maxScope <= 0 || maxScope > m_source.Count) { maxScope = m_source.Count; } if (maxScope - minScope < 2) { return; } float kx = rect.width / (m_maxX - m_minX); float ky = rect.height / (m_maxY - m_minY); Vector2 v1 = m_source[minScope]; v1.x = (v1.x - m_minX) * kx; v1.y = rect.height - (v1.y - m_minY) * ky; v1.x += rect.x; v1.y += rect.y; Vector2 v2; for (int i = (int)minScope + 1; i < maxScope; i++) { v2 = m_source[i]; v2.x = (v2.x - m_minX) * kx; v2.y = rect.height - (v2.y - m_minY) * ky; v2.x += rect.x; v2.y += rect.y; Drawing.DrawLine(v1, v2, color, width, false); if (pointRadius > 0) { Drawing.DrawCircle(v2, pointRadius, pointColor, width, false, 3); } v1 = v2; } } public void Draw(Rect rect) { Draw(rect, lineColor, lineWidth, pointColor, pointRadius, minScope, maxScope); } public void DrawLayout(params GUILayoutOption[] options) { GUILayout.Box("", options); Rect rect = GUILayoutUtility.GetLastRect(); Draw(rect, lineColor, lineWidth, pointColor, pointRadius, minScope, maxScope); } } } ================================================ FILE: SGFUnity/UI/UIDefine.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ namespace SGF.Unity.UI { public enum UITypeDef { Unkown = 0, Page = 1, Window=2, Widget = 3, Loading =4 } public class UILayerDef { public const int Background = 0; public const int Page = 1000;//-1999 public const int NormalWindow = 2000;//-2999 public const int TopWindow = 3000;//-3999 public const int Widget = 4000;//-4999 public const int Loading = 5000; public const int Unkown = 9999; public static int GetDefaultLayer(UITypeDef type) { switch (type) { case UITypeDef.Loading: return Loading; case UITypeDef.Widget: return Widget; case UITypeDef.Window: return NormalWindow; case UITypeDef.Page: return Page; case UITypeDef.Unkown: return Unkown; default: return Unkown; } } } } ================================================ FILE: SGFUnity/UI/UIElementBinder.cs ================================================ using System; using System.Linq; using System.Reflection; using UnityEngine; namespace SGF.Unity.UI { public class UIElementAttribute : Attribute { } public class UIElementBinder { public static void BindAllUIElement(MonoBehaviour parent) { var fis = parent.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); for (int i = 0; i < fis.Length; i++) { var fi = fis[i]; var tokens = fi.GetCustomAttributes(typeof(UIElementAttribute), true); if (tokens.Length > 0) { BindUIElement(parent, fi); } } } private static void BindUIElement(MonoBehaviour parent, FieldInfo fi) { Transform element = parent.transform.Find(fi.Name); string uiName = fi.Name; if (element == null) { if (uiName.StartsWith("m_")) { uiName = uiName.Substring(2); element = parent.transform.Find(uiName); } else if (uiName.StartsWith("_")) { uiName = uiName.Substring(1); element = parent.transform.Find(uiName); } } if (element == null) { var c = uiName[0]; c = Char.IsLower(c) ? Char.ToUpper(c) : Char.ToLower(c); uiName = c + uiName.Substring(1); element = parent.transform.Find(uiName); } if (element != null) { var value = element.GetComponent(fi.FieldType); fi.SetValue(parent, value); } else { Debuger.LogError("Canot Find UIElement:{0}", fi.Name); } } public static void BindUIElement(MonoBehaviour parent, string uiName) { var fis = parent.GetType().GetFields(); for (int i = 0; i < fis.Length; i++) { var fi = fis[i]; if (fi.Name == uiName) { BindUIElement(parent, fi); } } } } } ================================================ FILE: SGFUnity/UI/UIEventTrigger.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using UnityEngine; using UnityEngine.EventSystems; namespace SGF.Unity.UI { public class UIEventTrigger:EventTrigger { public Action onClick; public Action onClickWithObject; public Action onClickWithName; public Action onClickWithEvent; public Action onDown; public Action onEnter; public Action onExit; public Action onUp; public Action onBeginDrag; public Action onDrag; public Action onEndDrag; public Action onSelect; public Action onUpdateSelect; static public UIEventTrigger Get(GameObject go) { UIEventTrigger listener = go.GetComponent(); if (listener == null) listener = go.AddComponent(); return listener; } static public UIEventTrigger Get(UIBehaviour control) { UIEventTrigger listener = control.gameObject.GetComponent(); if (listener == null) listener = control.gameObject.AddComponent(); return listener; } static public UIEventTrigger Get(Transform transform) { UIEventTrigger listener = transform.gameObject.GetComponent(); if (listener == null) listener = transform.gameObject.AddComponent(); return listener; } static public bool HasExistOn(Transform transform) { return transform.gameObject.GetComponent() != null; } public override void OnPointerClick(PointerEventData eventData) { if (onClickWithObject != null) onClickWithObject(gameObject); if (onClick != null) onClick(); if (onClickWithEvent != null) onClickWithEvent(eventData); if (onClickWithName != null) onClickWithName(gameObject.name); } public override void OnPointerDown(PointerEventData eventData) { if (onDown != null) onDown(eventData); } public override void OnPointerEnter(PointerEventData eventData) { if (onEnter != null) onEnter(eventData); } public override void OnPointerExit(PointerEventData eventData) { if (onExit != null) onExit(eventData); } public override void OnPointerUp(PointerEventData eventData) { if (onUp != null) onUp(eventData); } public override void OnSelect(BaseEventData eventData) { if (onSelect != null) onSelect(eventData); } public override void OnUpdateSelected(BaseEventData eventData) { if (onUpdateSelect != null) onUpdateSelect(eventData); } public override void OnBeginDrag(PointerEventData eventData) { if (onBeginDrag != null) { onBeginDrag(eventData); } } public override void OnDrag(PointerEventData eventData) { if (onDrag != null) { onDrag(eventData); } } public override void OnEndDrag(PointerEventData eventData) { if (onEndDrag != null) { onEndDrag(eventData); } } } } ================================================ FILE: SGFUnity/UI/UILib/Control/CtlList.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using UnityEngine.UI; using UnityEngine; using System.Collections.Generic; using System.Collections; namespace SGF.Unity.UI.UILib.Control { public class CtlList:UIControl { enum Direction { Horizontal, Vertical } [SerializeField] private RectTransform m_itemTemplate; //页面的显示大小 [SerializeField] private Vector2 m_pageRect; [SerializeField] private Direction m_direction = Direction.Horizontal; [SerializeField, Range(4, 10)] private int m_bufferSize; private ScrollRect m_scrollRect; private RectTransform m_content; private RectTransform m_viewport; private List m_listItemObject = new List(); private IList m_datas; private int m_dataCount = 0; //宽高 public Vector2 ItemViewRect { get { return m_itemTemplate != null ? m_itemTemplate.sizeDelta : new Vector2(100, 100); }} public float ItemViewSize { get { return m_direction == Direction.Horizontal ? ItemViewRect.x : ItemViewRect.y; } } //行列 public Vector2 PageRect{get{return m_pageRect;}} public int PageSize { get { return m_direction == Direction.Horizontal ? (int)m_pageRect.x : (int)m_pageRect.y; } } //Content的位置 private float m_prevPos = 0; public float Position { get { return m_direction == Direction.Horizontal ? m_content.anchoredPosition.x : m_content.anchoredPosition.y; } } private int m_currentIndex;//页面的第一行(列)在整个content中的位置 //页面的实际大小(行列) private Vector2 m_pageRealRect = Vector2.zero; public Vector2 PageRealRect { get { if (m_pageRealRect == Vector2.zero) { float rows, cols; if (m_direction == Direction.Horizontal) { rows = m_pageRect.x; cols = m_pageRect.y + (float)m_bufferSize; } else { rows = m_pageRect.x + (float)m_bufferSize; cols = m_pageRect.y; } m_pageRealRect = new Vector2(rows, cols); } return m_pageRealRect; } } /// 由Data数量获取多少行多少列 private Vector2 MaxRectWithDatas { get { int num = m_datas != null ? m_datas.Count:0; return m_direction == Direction.Horizontal ? new Vector2(m_pageRect.x, Mathf.CeilToInt(num / m_pageRect.x)) : new Vector2(Mathf.CeilToInt(num / m_pageRect.y), m_pageRect.y); } } protected override void Awake() { base.Awake(); m_scrollRect = GetComponent(); m_scrollRect.horizontal = m_direction == Direction.Horizontal; m_scrollRect.vertical = m_direction == Direction.Vertical; m_content = m_scrollRect.content; m_viewport = m_scrollRect.viewport; } void Start() { if (m_direction == Direction.Vertical) { m_itemTemplate.sizeDelta = new Vector2(m_viewport.rect.width, m_itemTemplate.sizeDelta.y); } m_itemTemplate.gameObject.SetActive(false); } public void Clear() { SetData(new List()); } public override void SetData(object data) { object oldData = m_datas; m_datas = data as IList; m_dataCount = m_datas.Count; int pageItemCount = (int)m_pageRect.x * (int)m_pageRect.y; if (m_datas.Count > pageItemCount) { SetContentBound(MaxRectWithDatas); } else { SetContentBound(m_pageRect); } int pageRealItemCount = (int)PageRealRect.x * (int)PageRealRect.y; if (m_datas.Count > pageRealItemCount) { while (m_listItemObject.Count < pageRealItemCount) { CreateItem(m_listItemObject.Count); } } else { while (m_listItemObject.Count > m_datas.Count) { RemoveItem(m_listItemObject.Count - 1); } while (m_listItemObject.Count < m_datas.Count) { CreateItem(m_listItemObject.Count); } } if (oldData != data) { ValidateItems (); } } private void CreateItem(int index) { RectTransform item = Instantiate(m_itemTemplate); item.SetParent(m_content.transform, false); item.anchorMax = Vector2.up; item.anchorMin = Vector2.up; item.pivot = Vector2.up; item.name = "item" + index; item.anchoredPosition = m_direction == Direction.Horizontal ? new Vector2(Mathf.Floor(index / PageRealRect.x) * ItemViewRect.x, -(index % PageRealRect.x) * ItemViewRect.y) : new Vector2((index % PageRealRect.y) * ItemViewRect.x, -Mathf.Floor(index / PageRealRect.y) * ItemViewRect.y); m_listItemObject.Add(item); item.gameObject.SetActive(true); UpdateItem(index, item.gameObject); } private void RemoveItem(int index) { RectTransform item = m_listItemObject[index]; m_listItemObject.RemoveAt(index); Destroy(item.gameObject); } /// 设置content的大小 private void SetContentBound(Vector2 bound) { m_content.sizeDelta = new Vector2(bound.y * ItemViewRect.x, bound.x * ItemViewRect.y); } public float MaxPrevPos { get { float result; Vector2 max = MaxRectWithDatas; if (m_direction == Direction.Horizontal) { result = max.y - m_pageRect.y; } else { result = max.x - m_pageRect.x; } return result * ItemViewSize; } } private void ValidateItems() { for (int i = 0; i < m_listItemObject.Count; ++i) { UpdateItem (i, m_listItemObject [i].gameObject); } } void Update() { if (m_datas == null) { return; } if (m_datas != null && m_dataCount != m_datas.Count) { SetData(m_datas); } float dirAdjust = m_direction == Direction.Horizontal ? 1f : -1f; while (dirAdjust * Position - m_prevPos < -ItemViewSize * 2) { if (m_prevPos <= -MaxPrevPos) return; m_prevPos -= ItemViewSize; List range = m_listItemObject.GetRange(0, PageSize); m_listItemObject.RemoveRange(0, PageSize); m_listItemObject.AddRange(range); for (int i = 0; i < range.Count; i++) { MoveItemToIndex(m_currentIndex * PageSize + m_listItemObject.Count + i, range[i]); } m_currentIndex++; } while (dirAdjust * Position - m_prevPos > -ItemViewSize) { if (Mathf.RoundToInt(m_prevPos) >= 0) return; m_prevPos += ItemViewSize; m_currentIndex--; if (m_currentIndex < 0) return; List range = m_listItemObject.GetRange(m_listItemObject.Count - PageSize, PageSize); m_listItemObject.RemoveRange(m_listItemObject.Count - PageSize, PageSize); m_listItemObject.InsertRange(0, range); for (int i = 0; i < range.Count; i++) { MoveItemToIndex(m_currentIndex * PageSize + i, range[i]); } } } private void MoveItemToIndex(int index, RectTransform item) { item.anchoredPosition = GetItemPosByIndex(index); UpdateItem(index, item.gameObject); } private Vector2 GetItemPosByIndex(int index) { float x, y; if (m_direction == Direction.Horizontal) { x = index % m_pageRect.x; y = Mathf.FloorToInt(index / m_pageRect.x); } else { x = Mathf.FloorToInt(index / m_pageRect.y); y = index % m_pageRect.y; } return new Vector2(y * ItemViewRect.x, -x * ItemViewRect.y); } private void UpdateItem(int index, GameObject item) { item.SetActive(index < m_datas.Count); if (item.activeSelf) { CtlListItem itemComp = item.GetComponent < CtlListItem > (); if (itemComp != null) { itemComp.UpdateItem(index, m_datas[index]); } } } } } ================================================ FILE: SGFUnity/UI/UILib/Control/CtlListItem.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ namespace SGF.Unity.UI.UILib.Control { public class CtlListItem:UIControl { public CtlListItem() { } public virtual void UpdateItem(int index, object data) { } } } ================================================ FILE: SGFUnity/UI/UILib/Control/CtlProgressBar.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using UnityEngine.UI; namespace SGF.Unity.UI.UILib.Control { public class CtlProgressBar:UIControl { public Image imgProgressValue; public float progress = 0; void Start() { SetData(0f); } public override void SetData(object data) { this.progress = (float)data; imgProgressValue.fillAmount = progress; } } } ================================================ FILE: SGFUnity/UI/UILib/Control/UIControl.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using UnityEngine; using UnityEngine.EventSystems; namespace SGF.Unity.UI.UILib.Control { public class UIControl:MonoBehaviour { public bool AutoBindUIElement = false; protected virtual void Awake() { if (AutoBindUIElement) { UIElementBinder.BindAllUIElement(this); } } public virtual void SetData(object data) { } public void SetVisible(bool value) { this.gameObject.SetActive(value); } public static void SetVisible(UIBehaviour ui, bool value) { if (ui != null) { ui.gameObject.SetActive(value); } } public bool IsVisible { get { return this.gameObject.activeSelf;} } public static bool GetVisible(UIBehaviour ui) { return ui.gameObject.activeSelf; } } } ================================================ FILE: SGFUnity/UI/UILib/UIMsgBox.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; namespace SGF.Unity.UI.UILib { public class UIMsgBox:UIWindow { public class UIMsgBoxArg { public string title = ""; public string content = ""; public string btnText;//"确定|取消|关闭" } private UIMsgBoxArg m_arg; public Text txtContent; public UIBehaviour ctlTitle; public Button[] buttons; protected override void OnOpen(object arg = null) { base.OnOpen(arg); m_arg = arg as UIMsgBoxArg; txtContent.text = m_arg.content; string[] btnTexts = m_arg.btnText.Split('|'); UIUtils.SetChildText(ctlTitle, m_arg.title); UIUtils.SetActive(ctlTitle, !string.IsNullOrEmpty(m_arg.title)); float btnWidth = 200; float btnStartX = (1 - btnTexts.Length) * btnWidth / 2; for (int i = 0; i < buttons.Length; i++) { if (i < btnTexts.Length) { UIUtils.SetActive(buttons[i], true); UIUtils.SetButtonText(buttons[i], btnTexts[i]); Vector3 pos = buttons[i].transform.localPosition; pos.x = btnStartX + i * btnWidth; buttons[i].transform.localPosition = pos; } else { UIUtils.SetActive(buttons[i], false); } UIEventTrigger.Get(buttons[i]).onClickWithObject += OnBtnClick; } Layer = (UILayerDef.TopWindow); } protected override void OnClose(object arg = null) { base.OnClose(arg); for (int i = 0; i < buttons.Length; i++) { UIEventTrigger.Get(buttons[i]).onClickWithObject -= OnBtnClick; } } public void OnBtnClick(GameObject target) { Debuger.Log(target.name); int btnIndex = IndexOfButton(target); this.Close(btnIndex); } private int IndexOfButton(GameObject target) { for (int i = 0; i < buttons.Length; i++) { if (buttons[i].gameObject == target) { return i; } } return -1; } } } ================================================ FILE: SGFUnity/UI/UILib/UIMsgTips.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using UnityEngine.EventSystems; namespace SGF.Unity.UI.UILib { public class UIMsgTips:UIWidget { public UIBehaviour ctlTextBar; private const float MaxYOffset = 20f; private float m_alpha = 1; private float m_yOffset = MaxYOffset; protected override void OnOpen(object arg = null) { base.OnOpen(arg); UIUtils.SetChildText(ctlTextBar, arg as string); m_yOffset = MaxYOffset; m_alpha = 1; UpdateView(); } void Update() { m_alpha -= 0.01f; if (m_alpha < 0) { m_alpha = 0; this.Close(); } m_yOffset -= 0.1f; if (m_yOffset < 0) { m_yOffset = 0; } UpdateView(); } private void UpdateView() { ctlTextBar.transform.SetLocalY(MaxYOffset - m_yOffset); } } } ================================================ FILE: SGFUnity/UI/UILib/UISimpleLoading.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using SGF.Unity.UI.UILib.Control; using UnityEngine; using UnityEngine.UI; namespace SGF.Unity.UI.UILib { public class UISimpleLoading:UILoading { public CtlProgressBar progressBar; public Image rotateIcon; private UILoadingArg m_arg; public UILoadingArg arg { get { return m_arg; } } protected override void OnOpen(object arg = null) { base.OnOpen(arg); m_arg = arg as UILoadingArg; if(m_arg == null) { m_arg = new UILoadingArg(); } UpdateText(); } protected override void OnClose(object arg = null) { m_arg = null; base.OnClose(arg); } public void ShowProgress(string title, float progress) { m_arg.title = title; m_arg.progress = progress; } public void ShowProgress(float progress) { m_arg.progress = progress; } private void UpdateText() { if (txtTitle != null) { txtTitle.text = m_arg.title + "(" + (int)(m_arg.progress * 100) + "%)"; } if (txtTips != null) { txtTips.text = m_arg.tips; } } private void UpdateProgress() { if (progressBar != null) { progressBar.SetData(m_arg.progress); } } protected override void OnUpdate() { if (m_arg != null) { UpdateText(); UpdateProgress(); } if (rotateIcon != null) { rotateIcon.transform.Rotate(new Vector3(0, 0, -45 * UnityEngine.Time.deltaTime)); } } } } ================================================ FILE: SGFUnity/UI/UILoading.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using UnityEngine.UI; namespace SGF.Unity.UI { public class UILoadingArg { public string title = ""; public string tips = ""; public float progress = 0;//0~1 public override string ToString() { return string.Format("title:{0}, tips:{1}, progress:{2}", title, tips, progress); } } public abstract class UILoading:UIPanel { public override UITypeDef UIType { get { return UITypeDef.Loading; } } public Text txtTitle; public Text txtTips; private UILoadingArg m_arg; public UILoadingArg arg { get { return m_arg; } } protected override void OnOpen(object arg = null) { base.OnOpen(arg); m_arg = arg as UILoadingArg; if (m_arg == null) { m_arg = new UILoadingArg(); } UpdateText(); } public void ShowProgress(string title, float progress) { m_arg.tips = title; m_arg.progress = progress; } public void ShowProgress(float progress) { m_arg.progress = progress; } protected override void OnUpdate() { base.OnUpdate(); if (m_arg != null) { UpdateText(); UpdateProgress(); } } protected virtual void UpdateProgress() { } private void UpdateText() { if (txtTitle != null) { txtTitle.text = m_arg.title + "(" + (int)(m_arg.progress * 100) + "%)"; } if (txtTips != null) { txtTips.text = m_arg.tips; } } } } ================================================ FILE: SGFUnity/UI/UIManager.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * UI管理器 * UI Manager * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using SGF.Utils; using UnityEngine; using UnityEngine.SceneManagement; namespace SGF.Unity.UI { public class UIManager : Singleton { public static string MainScene = "Main"; public static string MainPage = "UIMainPage"; public static string SceneLoading = "SceneLoading"; class UIPageTrack { public string name; public object arg; public Type type; } private Stack m_pageTrackStack; private UIPageTrack m_currentPage; private List m_listLoadedPanel; private Action onSceneLoadedOnly; public UIManager() { m_pageTrackStack = new Stack(); m_listLoadedPanel = new List(); } public void Init(string uiResRoot) { UIRes.UIResRoot = uiResRoot; m_pageTrackStack.Clear(); m_listLoadedPanel.Clear(); SceneManager.sceneLoaded += (scene, mode) => { if (onSceneLoadedOnly != null) onSceneLoadedOnly(scene.name); }; } public void Clean() { CloseAllLoadedPanel(); m_pageTrackStack.Clear(); m_listLoadedPanel.Clear(); } private void CloseAllLoadedPanel() { for (int i = m_listLoadedPanel.Count - 1; i >= 0; i--) { var panel = m_listLoadedPanel[i]; if (panel == null) { m_listLoadedPanel.RemoveAt(i); } else if (panel.IsOpen) { panel.Close(); } } } private string GetShortUIName(string name) { int i = name.LastIndexOf("/"); if(i < 0) i = name.LastIndexOf("\\"); if (i < 0) return name; return name.Substring(i+1); } public T Open(string name, object arg = null, Type implType = null) where T : UIPanel { T ui = UIRoot.Find(GetShortUIName(name)); if (ui == null) { ui = Load(name, implType); } if (ui != null) { if (m_listLoadedPanel.IndexOf(ui) < 0) { m_listLoadedPanel.Add(ui); } ui.Open(arg); UIRoot.Sort(); } else { Debuger.LogError("UI不存在:{0}", name); } return ui; } private T Load(string name, Type implType) where T : UIPanel { T ui = default(T); GameObject original = UIRes.LoadPrefab(name); if (original != null) { GameObject go = GameObject.Instantiate(original); ui = go.GetComponent(); if (ui == null) { try { ui = go.AddComponent(implType) as T; } catch (Exception e) { Debuger.LogError("无法自动添加抽象的UIPanel"); } } if (ui != null) { go.name = GetShortUIName(name); UIRoot.AddChild(ui); } else { Debuger.LogError("Prefab没有增加对应组件: " + name); } } else { Debuger.LogError("Res Not Found: " + name); } return ui; } public UIPanel GetUI(string name) { string shortname = GetShortUIName(name); for (int i = 0; i < m_listLoadedPanel.Count; i++) { if (m_listLoadedPanel[i].name == shortname || m_listLoadedPanel[i].name == name) { return m_listLoadedPanel[i]; } } return null; } //========================================================================================== public void LoadScene(string scene, Action onLoadComplete) { onSceneLoadedOnly = (sceneName) => { if (sceneName == scene) { onSceneLoadedOnly = null; if (onLoadComplete != null) onLoadComplete(); CloseLoading(SceneLoading); } }; OpenLoading(SceneLoading); SceneManager.LoadScene(scene); } //========================================================================================== #region Page管理 public void OpenPage(string name, object arg = null) { Debuger.Log("name:{0}, arg:{1} ", name, arg); if (m_currentPage != null) { if (m_currentPage.name != name) { m_pageTrackStack.Push(m_currentPage); } } OpenPageWorker(name, arg, null); } public void GoBackPage() { if (m_pageTrackStack.Count > 0) { var track = m_pageTrackStack.Pop(); OpenPageWorker(track.name, track.arg, track.type); } else { EnterMainPage(); } } private void OpenPageWorker(string page, object arg, Type type) { m_currentPage = new UIPageTrack(); m_currentPage.name = page; m_currentPage.arg = arg; m_currentPage.type = type; CloseAllLoadedPanel(); Open(page, arg, type); } public void EnterMainPage() { m_pageTrackStack.Clear(); OpenPageInScene(MainScene, MainPage, null, null); } public void OpenPageInScene(string scene, string page) { OpenPageInScene(scene, page, null, null); } private void OpenPageInScene(string scene, string page, object arg, Type type) { Debuger.Log("scene:{0}, page:{1}, arg:{2} ", scene, page, arg); string oldScene = SceneManager.GetActiveScene().name; if (oldScene == scene) { OpenPageWorker(page, arg, type); } else { LoadScene(scene, () => { OpenPageWorker(page, arg, type); }); } } #endregion //======================================================================= #region UIWindow管理 public UIWindow OpenWindow(string name, object arg = null) { Debuger.Log(name); UIWindow ui = Open(name, arg); return ui; } public void CloseWindow(string name, object arg = null) { Debuger.Log(name); UIWindow ui = GetUI(name) as UIWindow; if (ui != null) { ui.Close(arg); } } #endregion //======================================================================= #region UIWidget管理 public UIWidget OpenWidget(string name, object arg = null) { Debuger.Log(name); UIWidget ui = Open(name, arg); return ui; } public void CloseWidget(string name, object arg = null) { Debuger.Log(name); UIWidget ui = GetUI(name) as UIWidget; if (ui != null) { ui.Close(arg); } } #endregion //========================================================================================== #region UILoading管理 public UILoading OpenLoading(string name, object arg = null) { Debuger.Log(name); UILoading ui = Open(name, arg); return ui; } public void CloseLoading(string name, object arg = null) { Debuger.Log(name); UILoading ui = GetUI(name) as UILoading; if (ui != null) { ui.Close(arg); } } #endregion //========================================================================================== } } ================================================ FILE: SGFUnity/UI/UIPage.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using UnityEngine; using UnityEngine.UI; namespace SGF.Unity.UI { public abstract class UIPage:UIPanel { public override UITypeDef UIType { get { return UITypeDef.Page; } } /// /// 返回按钮,大部分Page都会有返回按钮 /// [SerializeField] private Button m_btnGoBack; /// /// 当UIPage被激活时调用 /// protected override void OnEnable() { Debuger.Log(); AddUIClickListener(m_btnGoBack, OnBtnGoBack); } /// /// 当UI不可用时调用 /// protected override void OnDisable() { Debuger.Log(); RemoveUIClickListeners(m_btnGoBack); } /// /// 当点击“返回”时调用 /// 但是并不是每一个Page都有返回按钮 /// private void OnBtnGoBack() { Debuger.Log(); UIManager.Instance.GoBackPage(); } } } ================================================ FILE: SGFUnity/UI/UIPanel.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using SGF.SEvent; using UnityEngine; using UnityEngine.EventSystems; namespace SGF.Unity.UI { public abstract class UIPanel:MonoBehaviour, ILogTag { public virtual UITypeDef UIType { get { return UITypeDef.Unkown; } } private int m_layer = UILayerDef.Unkown; public int Layer { get { return m_layer; } set { m_layer = value; } } public bool AutoBindUIElement = false; [SerializeField] private AnimationClip m_openAniClip; [SerializeField] private AnimationClip m_closeAniClip; private float m_closeAniClipTime; private object m_closeArg; public Signal onClose = new Signal(); /// /// 当前UI是否打开 /// public bool IsOpen { get { return this.gameObject.activeSelf; } } void Awake() { LOG_TAG = this.GetType().Name; if (AutoBindUIElement) { UIElementBinder.BindAllUIElement(this); } OnAwake(); } protected virtual void OnAwake() { } protected virtual void OnDestroy() { } protected virtual void OnEnable() { } protected virtual void OnDisable() { } private void Update() { if (m_closeAniClipTime > 0) { m_closeAniClipTime -= UnityEngine.Time.deltaTime; if (m_closeAniClipTime <= 0) { CloseWorker(); } } OnUpdate(); } public void Open(object arg = null) { LOG_TAG = this.GetType().Name; this.Log("args:{0}", arg); if (!this.gameObject.activeSelf) { this.gameObject.SetActive(true); } OnOpen(arg); if (m_openAniClip != null) { var animation = GetComponent(); if (animation != null) { animation.Play(m_openAniClip.name); } else { Debuger.LogError("设置了OpenAniClip,但是未找到 Animation组件!"); } } } public void Close(object arg = null) { this.Log("args:{0}", arg); m_closeArg = arg; m_closeAniClipTime = 0; if (m_closeAniClip != null) { var animation = GetComponent(); if (animation != null) { animation.Play(m_closeAniClip.name); m_closeAniClipTime = m_closeAniClip.length; } else { Debuger.LogError("设置了CloseAniClip,但是未找到 Animation组件!"); CloseWorker(); } } else { CloseWorker(); } } private void CloseWorker() { if (this.gameObject.activeSelf) { this.gameObject.SetActive(false); } OnClose(m_closeArg); onClose.Invoke(m_closeArg); m_closeArg = null; } protected virtual void OnOpen(object arg = null) { Layer = UILayerDef.GetDefaultLayer(UIType); } protected virtual void OnClose(object arg = null) { } protected virtual void OnUpdate() { } public string LOG_TAG { get; protected set; } /// /// 方便寻找Panel上的UI控件 /// /// /// /// public T Find(string controlName) where T : MonoBehaviour { Transform target = this.transform.Find(controlName); if (target != null) { return target.GetComponent(); } else { Debuger.LogError("未找到UI控件:{0}", controlName); return default(T); } } #region UI事件监听辅助函数 /// /// 为UIPanel内的脚本提供便捷的UI事件监听接口 /// /// /// public void AddUIClickListener(string controlName, Action listener) { Transform target = this.transform.Find(controlName); if (target != null) { UIEventTrigger.Get(target).onClickWithName -= listener; UIEventTrigger.Get(target).onClickWithName += listener; } else { Debuger.LogError("未找到UI控件:{0}", controlName); } } /// /// 为UIPanel内的脚本提供便捷的UI事件监听接口 /// /// /// public void AddUIClickListener(string controlName, Action listener) { Transform target = this.transform.Find(controlName); if (target != null) { UIEventTrigger.Get(target).onClick -= listener; UIEventTrigger.Get(target).onClick += listener; } else { Debuger.LogError("未找到UI控件:{0}", controlName); } } /// /// 为UIPanel内的脚本提供便捷的UI事件监听接口 /// /// /// public void AddUIClickListener(UIBehaviour target, Action listener) { if (target != null) { UIEventTrigger.Get(target).onClick -= listener; UIEventTrigger.Get(target).onClick += listener; } } /// /// 移除UI控件的监听器 /// /// /// public void RemoveUIClickListener(string controlName, Action listener) { Transform target = this.transform.Find(controlName); if (target != null) { if (UIEventTrigger.HasExistOn(target)) { UIEventTrigger.Get(target).onClickWithName -= listener; } } else { Debuger.LogError("未找到UI控件:{0}", controlName); } } /// /// 移除UI控件的监听器 /// /// /// public void RemoveUIClickListener(string controlName, Action listener) { Transform target = this.transform.Find(controlName); if (target != null) { if (UIEventTrigger.HasExistOn(target)) { UIEventTrigger.Get(target).onClick -= listener; } } else { Debuger.LogError("未找到UI控件:{0}", controlName); } } /// /// 移除UI控件的监听器 /// /// /// public void RemoveUIClickListener(UIBehaviour target, Action listener) { if (target != null) { if (UIEventTrigger.HasExistOn(target.transform)) { UIEventTrigger.Get(target).onClick -= listener; } } } /// /// 移除UI控件的所有监听器 /// /// public void RemoveUIClickListeners(string controlName) { Transform target = this.transform.Find(controlName); if (target != null) { if (UIEventTrigger.HasExistOn(target)) { UIEventTrigger.Get(target).onClick = null; } } else { Debuger.LogError("未找到UI控件:{0}", controlName); } } /// /// 移除UI控件的所有监听器 /// /// public void RemoveUIClickListeners(UIBehaviour target) { if (target != null) { if (UIEventTrigger.HasExistOn(target.transform)) { UIEventTrigger.Get(target).onClick = null; } } } #endregion } } ================================================ FILE: SGFUnity/UI/UIRes.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using UnityEngine; namespace SGF.Unity.UI { public static class UIRes { public static string UIResRoot = "ui/"; /// /// 加载UI的Prefab /// /// /// public static GameObject LoadPrefab(string name) { GameObject asset = (GameObject)Resources.Load(UIResRoot + name); return asset; } } } ================================================ FILE: SGFUnity/UI/UIRoot.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; namespace SGF.Unity.UI { public class UIRoot:MonoBehaviour { /// /// 从UIRoot下通过名字&类型寻找一个组件对象 /// /// /// /// public static T Find(string name) where T : MonoBehaviour { GameObject obj = Find(name); if (obj != null) { return obj.GetComponent(); } return null; } public static GameObject Find(string name) { if (string.IsNullOrEmpty(name)) { return null; } Transform obj = null; GameObject root = FindUIRoot(); if (root != null) { //在新版Unity中,Find函数会将Name中的/当作分隔符 //obj = root.transform.FindChild(name); Transform t = root.transform; for (int i = 0; i < t.childCount; i++) { Transform c = t.GetChild(i); if (c.name == name) { obj = c; break; } } } if (obj != null) { return obj.gameObject; } return null; } public static GameObject FindUIRoot() { GameObject root = GameObject.Find("UIRoot"); if (root != null && root.GetComponent() != null) { return root; } Debuger.LogError("UIRoot Is Not Exist!!!"); return null; } /// /// 当一个UIPage/UIWindow/UIWidget添加到UIRoot下面 /// /// public static void AddChild(UIPanel child) { GameObject root = FindUIRoot(); if (root == null || child == null) { return; } child.transform.SetParent(root.transform, false); } public static void Sort() { GameObject root = FindUIRoot(); if (root == null) { return; } List list = new List(); root.GetComponentsInChildren(true, list); list.Sort((a, b) => { return a.Layer - b.Layer; }); for (int i = 0; i < list.Count; i++) { list[i].transform.SetSiblingIndex(i); } } //============================================================================== //UIRoot本身的逻辑 //============================================================================== private static Camera m_uiCamera; private static CanvasScaler m_canvasScaler; public Camera UICamera; void Awake() { //让UIRoot一直存在于所有场景中 DontDestroyOnLoad(gameObject); m_uiCamera = UICamera; m_canvasScaler = GetComponent(); } public CanvasScaler GetUIScaler() { return m_canvasScaler; } public Camera GetUICamera() { return m_uiCamera; } } } ================================================ FILE: SGFUnity/UI/UIUtils.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using SGF.Unity.Utils; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; namespace SGF.Unity.UI { /// /// 为UI操作提供基础封装,使UI操作更方便 /// public static class UIUtils { /// /// 设置一个UI元素是否可见 /// /// /// public static void SetActive(UIBehaviour ui, bool value) { if (ui != null && ui.gameObject != null) { GameObjectUtils.SetActiveRecursively(ui.gameObject, value); } } public static void SetButtonText(Button btn, string text) { Text objText = btn.transform.GetComponentInChildren(); if (objText != null) { objText.text = text; } } public static string GetButtonText(Button btn) { Text objText = btn.transform.GetComponentInChildren(); if (objText != null) { return objText.text; } return ""; } public static void SetChildText(UIBehaviour ui, string text) { Text objText = ui.transform.GetComponentInChildren(); if (objText != null) { objText.text = text; } } /// /// 方便寻找Panel上的UI控件 /// /// /// /// public static T Find(MonoBehaviour parent, string controlName) where T : MonoBehaviour { Transform target = parent.transform.Find(controlName); if (target != null) { return target.GetComponent(); } else { Debuger.LogError("未找到UI控件:{0}", controlName); return default(T); } } } } ================================================ FILE: SGFUnity/UI/UIWidget.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ namespace SGF.Unity.UI { public abstract class UIWidget : UIPanel { public override UITypeDef UIType { get { return UITypeDef.Widget; } } } } ================================================ FILE: SGFUnity/UI/UIWindow.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using UnityEngine; using UnityEngine.UI; namespace SGF.Unity.UI { public abstract class UIWindow:UIPanel { public override UITypeDef UIType { get { return UITypeDef.Window; } } [SerializeField] private Button m_btnClose; /// /// 当UI可用时调用 /// protected override void OnEnable() { Debuger.Log(); AddUIClickListener(m_btnClose, OnBtnClose); } /// /// 当UI不可用时调用 /// protected override void OnDisable() { Debuger.Log(); RemoveUIClickListeners(m_btnClose); } private void OnBtnClose() { Close(0); } } } ================================================ FILE: SGFUnity/Utils/GameObjectUtils.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using UnityEngine; namespace SGF.Unity.Utils { public static class GameObjectUtils { public static T EnsureComponent(this GameObject target) where T : Component { T comp = target.GetComponent(); if (comp == null) { return target.AddComponent(); } return comp; } public static Component EnsureComponent(this GameObject target, Type type) { Component comp = target.GetComponent(type); if (comp == null) { return target.AddComponent(type); } return comp; } public static T FindComponent(this GameObject target, string path) where T : Component { GameObject obj = FindGameObject(target, path); if (obj != null) { return obj.GetComponent(); } return default(T); } public static GameObject FindGameObject(this GameObject target, string path) { if (target != null) { Transform t = target.transform.Find(path); if (t != null) { return t.gameObject; } } return null; } private static GameObject FindGameObject2(GameObject target, string path) { if (target == null) { return null; } string[] array = path.Split('.'); Transform current = target.transform; for (int i = 0; i < array.Length; ++i) { string name = array[i]; Transform child = current.Find(name); if (child != null) { current = child; } else { char[] c = name.ToCharArray(); if (Char.IsLower(c[0])) { c[0] = Char.ToUpper(c[0]); } else { c[0] = Char.ToLower(c[0]); } name = new string(c); child = current.Find(name); if (child != null) { current = child; } else { current = null; break; } } } if (current == null) { return null; } return current.gameObject; } public static GameObject FindGameObjbyName(this GameObject root, string name) { if (root == null) { return GameObject.Find(name); } Transform[] childs = root.GetComponentsInChildren(); foreach (Transform trans in childs) { if (trans.gameObject.name.Equals(name)) { return trans.gameObject; } } return null; } public static GameObject FindFirstGameObjByPrefix(this GameObject root, string prefix) { Transform[] childs; if (root != null) { childs = root.GetComponentsInChildren(); } else { childs = GameObject.FindObjectsOfType(); } foreach (Transform trans in childs) { if (trans.gameObject.name.Length >= prefix.Length) { if (trans.gameObject.name.Substring(0, prefix.Length) == prefix) { return trans.gameObject; } } } return null; } public static void SetActiveRecursively(this GameObject target, bool bActive) { #if (!UNITY_3_5) for (int n = target.transform.childCount - 1; 0 <= n; n--) if (n < target.transform.childCount) SetActiveRecursively(target.transform.GetChild(n).gameObject, bActive); target.SetActive(bActive); #else target.SetActiveRecursively(bActive); #endif } public static void SetLayerRecursively(this GameObject target, int layer) { #if (!UNITY_3_5) for (int n = target.transform.childCount - 1; 0 <= n; n--) { if (n < target.transform.childCount) { SetLayerRecursively(target.transform.GetChild(n).gameObject, layer); } } target.layer = layer; #else target.SetActiveRecursively(bActive); #endif } } } ================================================ FILE: SGFUnity/Utils/NetUtils.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using UnityEngine; namespace SGF.Unity.Utils { public class NetUtils { public static bool IsWifi() { return Application.internetReachability == NetworkReachability.ReachableViaLocalAreaNetwork; } public static bool IsAvailable() { return Application.internetReachability != NetworkReachability.NotReachable; } public static string SelfIP { get { return UnityEngine.Network.player.ipAddress; } } } } ================================================ FILE: SGFUnity/Utils/QRCodeUtils.cs ================================================ /* * Copyright (C) 2018 Slicol Tang. All rights reserved. * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ using System; using SGF; using UnityEngine; using ZXing; using ZXing.Common; namespace OT.Foundation { public class QRCodeUtils { public const string LOG_TAG = "QRCodeUtils"; public static Texture2D EncodeToImage(string content, int width, int height) { Debuger.Log(LOG_TAG, "EncodeToImage", "content:{0}, width:{1}, height:{2}", content, width, height); Texture2D texEncoded = null; BitMatrix bm = null; try { MultiFormatWriter mfw = new MultiFormatWriter(); bm = mfw.encode(content, BarcodeFormat.QR_CODE, width, height); } catch (Exception e) { Debuger.LogError(LOG_TAG, "EncodeToImage", e.Message); return null; } texEncoded = new Texture2D(width, height); for (int x = 0; x < bm.Height; x++) { for (int y = 0; y < bm.Width; y++) { int py = x; int px = y; if (bm[x, y]) { texEncoded.SetPixel(px,py, Color.black); } else { texEncoded.SetPixel(px, py, Color.white); } } } texEncoded.Apply(); return texEncoded; } public static string DecodeFromImage(Texture2D image) { Debuger.Log(LOG_TAG, "DecodeFromImage"); try { Color32LuminanceSource src = new Color32LuminanceSource(image.GetPixels32(), image.width, image.height); Binarizer bin = new GlobalHistogramBinarizer(src); BinaryBitmap bmp = new BinaryBitmap(bin); MultiFormatReader mfr = new MultiFormatReader(); Result result = mfr.decode(bmp); if (result != null) { return result.Text; } else { Debuger.LogError(LOG_TAG, "DecodeFromImage", "Decode 失败!"); } } catch (Exception e) { Debuger.LogError(LOG_TAG, "DecodeFromImage", e.Message); } return ""; } } } ================================================ FILE: SGFUnityTest/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // 有关程序集的一般信息由以下 // 控制。更改这些特性值可修改 // 与程序集关联的信息。 [assembly: AssemblyTitle("SGFUnityTest")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("SGFUnityTest")] [assembly: AssemblyCopyright("Copyright © 2018")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] //将 ComVisible 设置为 false 将使此程序集中的类型 //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, //请将此类型的 ComVisible 特性设置为 true。 [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID [assembly: Guid("dc93629f-df4e-406f-ac5f-df96f3f98cbc")] // 程序集的版本信息由下列四个值组成: // // 主版本 // 次版本 // 生成号 // 修订号 // //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, // 方法是按如下所示使用“*”: : // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: SGFUnityTest/SGFUnityTest.csproj ================================================  Debug AnyCPU {DC93629F-DF4E-406F-AC5F-DF96F3F98CBC} Library Properties SGFUnityTest SGFUnityTest v4.0 512 {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages False UnitTest true full false bin\Debug\ DEBUG;TRACE prompt 4 pdbonly true bin\Release\ TRACE prompt 4 3.5 False False False False ================================================ FILE: SGFUnityTest/UnitTest1.cs ================================================ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace SGFUnityTest { [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod1() { } } }